blob: f1148e2e5d022dc8ec0b1b92f8db8a5a93bfb38e [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
Ronald Oussoren19302d92006-06-11 14:33:36 +000014import macosxSupport
David Scherer7aced172000-08-15 01:13:23 +000015
16import linecache
17from code import InteractiveInterpreter
18
Kurt B. Kaiser2303b1c2003-11-24 05:26:16 +000019try:
20 from Tkinter import *
21except ImportError:
22 print>>sys.__stderr__, "** IDLE can't import Tkinter. " \
23 "Your Python may not be configured for Tk. **"
24 sys.exit(1)
David Scherer7aced172000-08-15 01:13:23 +000025import tkMessageBox
26
27from EditorWindow import EditorWindow, fixwordbreaks
28from FileList import FileList
29from ColorDelegator import ColorDelegator
30from UndoDelegator import UndoDelegator
Kurt B. Kaiser969de452002-06-12 03:28:57 +000031from OutputWindow import OutputWindow
Steven M. Gava99300612001-11-04 07:03:08 +000032from configHandler import idleConf
David Scherer7aced172000-08-15 01:13:23 +000033import idlever
34
Chui Tey5d2af632002-05-26 13:36:41 +000035import rpc
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +000036import Debugger
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +000037import RemoteDebugger
Chui Tey5d2af632002-05-26 13:36:41 +000038
Kurt B. Kaiserb9764192002-09-23 04:10:37 +000039IDENTCHARS = string.ascii_letters + string.digits + "_"
Kurt B. Kaiser24d7e0c2003-06-05 23:51:29 +000040LOCALHOST = '127.0.0.1'
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:
58 def idle_showwarning(message, category, filename, lineno):
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000059 file = warning_stream
60 try:
61 file.write(warnings.formatwarning(message, category, filename, lineno))
62 except IOError:
63 pass ## file (probably __stderr__) is invalid, warning dropped.
Chui Tey5d2af632002-05-26 13:36:41 +000064 warnings.showwarning = idle_showwarning
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000065 def idle_formatwarning(message, category, filename, lineno):
66 """Format warnings the IDLE way"""
67 s = "\nWarning (from warnings module):\n"
68 s += ' File \"%s\", line %s\n' % (filename, lineno)
69 line = linecache.getline(filename, lineno).strip()
70 if line:
71 s += " %s\n" % line
72 s += "%s: %s\n>>> " % (category.__name__, message)
73 return s
74 warnings.formatwarning = idle_formatwarning
Chui Tey5d2af632002-05-26 13:36:41 +000075
Kurt B. Kaiserf7a88992004-11-13 21:05:58 +000076def extended_linecache_checkcache(filename=None,
77 orig_checkcache=linecache.checkcache):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +000078 """Extend linecache.checkcache to preserve the <pyshell#...> entries
79
Kurt B. Kaiserf7a88992004-11-13 21:05:58 +000080 Rather than repeating the linecache code, patch it to save the
81 <pyshell#...> entries, call the original linecache.checkcache()
82 (which destroys them), and then restore the saved entries.
83
84 orig_checkcache is bound at definition time to the original
85 method, allowing it to be patched.
Kurt B. Kaiser45186c42002-10-23 04:48:08 +000086
87 """
David Scherer7aced172000-08-15 01:13:23 +000088 cache = linecache.cache
89 save = {}
90 for filename in cache.keys():
91 if filename[:1] + filename[-1:] == '<>':
92 save[filename] = cache[filename]
93 orig_checkcache()
94 cache.update(save)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +000095
Kurt B. Kaiser81885592002-11-29 22:10:53 +000096# Patch linecache.checkcache():
97linecache.checkcache = extended_linecache_checkcache
David Scherer7aced172000-08-15 01:13:23 +000098
Kurt B. Kaiser45186c42002-10-23 04:48:08 +000099
David Scherer7aced172000-08-15 01:13:23 +0000100class PyShellEditorWindow(EditorWindow):
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000101 "Regular text edit window in IDLE, supports breakpoints"
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000102
David Scherer7aced172000-08-15 01:13:23 +0000103 def __init__(self, *args):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000104 self.breakpoints = []
Raymond Hettinger931237e2003-07-09 18:48:24 +0000105 EditorWindow.__init__(self, *args)
David Scherer7aced172000-08-15 01:13:23 +0000106 self.text.bind("<<set-breakpoint-here>>", self.set_breakpoint_here)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000107 self.text.bind("<<clear-breakpoint-here>>", self.clear_breakpoint_here)
David Scherer7aced172000-08-15 01:13:23 +0000108 self.text.bind("<<open-python-shell>>", self.flist.open_shell)
109
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000110 self.breakpointPath = os.path.join(idleConf.GetUserCfgDir(),
111 'breakpoints.lst')
Chui Teya2adb0f2002-11-04 22:14:54 +0000112 # whenever a file is changed, restore breakpoints
113 if self.io.filename: self.restore_file_breaks()
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000114 def filename_changed_hook(old_hook=self.io.filename_change_hook,
115 self=self):
Chui Teya2adb0f2002-11-04 22:14:54 +0000116 self.restore_file_breaks()
117 old_hook()
118 self.io.set_filename_change_hook(filename_changed_hook)
119
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000120 rmenu_specs = [("Set Breakpoint", "<<set-breakpoint-here>>"),
121 ("Clear Breakpoint", "<<clear-breakpoint-here>>")]
David Scherer7aced172000-08-15 01:13:23 +0000122
Chui Teya2adb0f2002-11-04 22:14:54 +0000123 def set_breakpoint(self, lineno):
124 text = self.text
125 filename = self.io.filename
126 text.tag_add("BREAK", "%d.0" % lineno, "%d.0" % (lineno+1))
127 try:
128 i = self.breakpoints.index(lineno)
129 except ValueError: # only add if missing, i.e. do once
130 self.breakpoints.append(lineno)
131 try: # update the subprocess debugger
132 debug = self.flist.pyshell.interp.debugger
133 debug.set_breakpoint_here(filename, lineno)
134 except: # but debugger may not be active right now....
135 pass
136
David Scherer7aced172000-08-15 01:13:23 +0000137 def set_breakpoint_here(self, event=None):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000138 text = self.text
139 filename = self.io.filename
140 if not filename:
141 text.bell()
David Scherer7aced172000-08-15 01:13:23 +0000142 return
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000143 lineno = int(float(text.index("insert")))
Chui Teya2adb0f2002-11-04 22:14:54 +0000144 self.set_breakpoint(lineno)
David Scherer7aced172000-08-15 01:13:23 +0000145
Kurt B. Kaiser669f4c32002-06-20 04:01:47 +0000146 def clear_breakpoint_here(self, event=None):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000147 text = self.text
148 filename = self.io.filename
149 if not filename:
150 text.bell()
Kurt B. Kaiser669f4c32002-06-20 04:01:47 +0000151 return
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000152 lineno = int(float(text.index("insert")))
153 try:
154 self.breakpoints.remove(lineno)
155 except:
156 pass
157 text.tag_remove("BREAK", "insert linestart",\
158 "insert lineend +1char")
159 try:
160 debug = self.flist.pyshell.interp.debugger
161 debug.clear_breakpoint_here(filename, lineno)
162 except:
163 pass
164
165 def clear_file_breaks(self):
166 if self.breakpoints:
167 text = self.text
168 filename = self.io.filename
169 if not filename:
170 text.bell()
171 return
172 self.breakpoints = []
173 text.tag_remove("BREAK", "1.0", END)
174 try:
175 debug = self.flist.pyshell.interp.debugger
176 debug.clear_file_breaks(filename)
177 except:
178 pass
179
Chui Teya2adb0f2002-11-04 22:14:54 +0000180 def store_file_breaks(self):
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000181 "Save breakpoints when file is saved"
182 # XXX 13 Dec 2002 KBK Currently the file must be saved before it can
183 # be run. The breaks are saved at that time. If we introduce
184 # a temporary file save feature the save breaks functionality
185 # needs to be re-verified, since the breaks at the time the
186 # temp file is created may differ from the breaks at the last
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000187 # permanent save of the file. Currently, a break introduced
188 # after a save will be effective, but not persistent.
189 # This is necessary to keep the saved breaks synched with the
190 # saved file.
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000191 #
192 # Breakpoints are set as tagged ranges in the text. Certain
193 # kinds of edits cause these ranges to be deleted: Inserting
194 # or deleting a line just before a breakpoint, and certain
195 # deletions prior to a breakpoint. These issues need to be
196 # investigated and understood. It's not clear if they are
197 # Tk issues or IDLE issues, or whether they can actually
198 # be fixed. Since a modified file has to be saved before it is
199 # run, and since self.breakpoints (from which the subprocess
200 # debugger is loaded) is updated during the save, the visible
201 # breaks stay synched with the subprocess even if one of these
202 # unexpected breakpoint deletions occurs.
203 breaks = self.breakpoints
204 filename = self.io.filename
Chui Teya2adb0f2002-11-04 22:14:54 +0000205 try:
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000206 lines = open(self.breakpointPath,"r").readlines()
Chui Teya2adb0f2002-11-04 22:14:54 +0000207 except IOError:
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000208 lines = []
209 new_file = open(self.breakpointPath,"w")
Chui Teya2adb0f2002-11-04 22:14:54 +0000210 for line in lines:
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000211 if not line.startswith(filename + '='):
Chui Teya2adb0f2002-11-04 22:14:54 +0000212 new_file.write(line)
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000213 self.update_breakpoints()
214 breaks = self.breakpoints
215 if breaks:
216 new_file.write(filename + '=' + str(breaks) + '\n')
Chui Teya2adb0f2002-11-04 22:14:54 +0000217 new_file.close()
218
219 def restore_file_breaks(self):
220 self.text.update() # this enables setting "BREAK" tags to be visible
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000221 filename = self.io.filename
222 if filename is None:
223 return
Chui Tey69371d62002-11-04 23:39:45 +0000224 if os.path.isfile(self.breakpointPath):
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000225 lines = open(self.breakpointPath,"r").readlines()
Chui Tey69371d62002-11-04 23:39:45 +0000226 for line in lines:
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000227 if line.startswith(filename + '='):
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000228 breakpoint_linenumbers = eval(line[len(filename)+1:])
Chui Tey69371d62002-11-04 23:39:45 +0000229 for breakpoint_linenumber in breakpoint_linenumbers:
230 self.set_breakpoint(breakpoint_linenumber)
Chui Teya2adb0f2002-11-04 22:14:54 +0000231
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000232 def update_breakpoints(self):
233 "Retrieves all the breakpoints in the current window"
Chui Teya2adb0f2002-11-04 22:14:54 +0000234 text = self.text
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000235 ranges = text.tag_ranges("BREAK")
236 linenumber_list = self.ranges_to_linenumbers(ranges)
237 self.breakpoints = linenumber_list
238
239 def ranges_to_linenumbers(self, ranges):
240 lines = []
241 for index in range(0, len(ranges), 2):
242 lineno = int(float(ranges[index]))
243 end = int(float(ranges[index+1]))
244 while lineno < end:
245 lines.append(lineno)
246 lineno += 1
247 return lines
248
Kurt B. Kaiser11220fa2002-12-24 00:57:22 +0000249# XXX 13 Dec 2002 KBK Not used currently
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000250# def saved_change_hook(self):
251# "Extend base method - clear breaks if module is modified"
252# if not self.get_saved():
253# self.clear_file_breaks()
254# EditorWindow.saved_change_hook(self)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000255
256 def _close(self):
257 "Extend base method - clear breaks when module is closed"
258 self.clear_file_breaks()
259 EditorWindow._close(self)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000260
David Scherer7aced172000-08-15 01:13:23 +0000261
262class PyShellFileList(FileList):
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000263 "Extend base class: IDLE supports a shell and breakpoints"
David Scherer7aced172000-08-15 01:13:23 +0000264
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000265 # override FileList's class variable, instances return PyShellEditorWindow
266 # instead of EditorWindow when new edit windows are created.
David Scherer7aced172000-08-15 01:13:23 +0000267 EditorWindow = PyShellEditorWindow
268
269 pyshell = None
270
271 def open_shell(self, event=None):
272 if self.pyshell:
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000273 self.pyshell.top.wakeup()
David Scherer7aced172000-08-15 01:13:23 +0000274 else:
275 self.pyshell = PyShell(self)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000276 if self.pyshell:
277 if not self.pyshell.begin():
278 return None
David Scherer7aced172000-08-15 01:13:23 +0000279 return self.pyshell
280
281
282class ModifiedColorDelegator(ColorDelegator):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000283 "Extend base class: colorizer for the shell window itself"
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000284
Steven M. Gavab77d3432002-03-02 07:16:21 +0000285 def __init__(self):
286 ColorDelegator.__init__(self)
287 self.LoadTagDefs()
David Scherer7aced172000-08-15 01:13:23 +0000288
289 def recolorize_main(self):
290 self.tag_remove("TODO", "1.0", "iomark")
291 self.tag_add("SYNC", "1.0", "iomark")
292 ColorDelegator.recolorize_main(self)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000293
Steven M. Gavab77d3432002-03-02 07:16:21 +0000294 def LoadTagDefs(self):
295 ColorDelegator.LoadTagDefs(self)
296 theme = idleConf.GetOption('main','Theme','name')
297 self.tagdefs.update({
298 "stdin": {'background':None,'foreground':None},
299 "stdout": idleConf.GetHighlight(theme, "stdout"),
300 "stderr": idleConf.GetHighlight(theme, "stderr"),
301 "console": idleConf.GetHighlight(theme, "console"),
Steven M. Gavab77d3432002-03-02 07:16:21 +0000302 })
David Scherer7aced172000-08-15 01:13:23 +0000303
David Scherer7aced172000-08-15 01:13:23 +0000304class ModifiedUndoDelegator(UndoDelegator):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000305 "Extend base class: forbid insert/delete before the I/O mark"
David Scherer7aced172000-08-15 01:13:23 +0000306
307 def insert(self, index, chars, tags=None):
308 try:
309 if self.delegate.compare(index, "<", "iomark"):
310 self.delegate.bell()
311 return
312 except TclError:
313 pass
314 UndoDelegator.insert(self, index, chars, tags)
315
316 def delete(self, index1, index2=None):
317 try:
318 if self.delegate.compare(index1, "<", "iomark"):
319 self.delegate.bell()
320 return
321 except TclError:
322 pass
323 UndoDelegator.delete(self, index1, index2)
324
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000325
326class MyRPCClient(rpc.RPCClient):
327
328 def handle_EOF(self):
329 "Override the base class - just re-raise EOFError"
330 raise EOFError
331
Kurt B. Kaiser8d1f11b2003-05-26 22:20:34 +0000332
David Scherer7aced172000-08-15 01:13:23 +0000333class ModifiedInterpreter(InteractiveInterpreter):
334
335 def __init__(self, tkconsole):
336 self.tkconsole = tkconsole
337 locals = sys.modules['__main__'].__dict__
338 InteractiveInterpreter.__init__(self, locals=locals)
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000339 self.save_warnings_filters = None
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000340 self.restarting = False
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000341 self.subprocess_arglist = self.build_subprocess_arglist()
David Scherer7aced172000-08-15 01:13:23 +0000342
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000343 port = 8833
Chui Tey5d2af632002-05-26 13:36:41 +0000344 rpcclt = None
345 rpcpid = None
346
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000347 def spawn_subprocess(self):
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000348 args = self.subprocess_arglist
Kurt B. Kaiserb7855182003-08-14 14:54:28 +0000349 self.rpcpid = os.spawnv(os.P_NOWAIT, sys.executable, args)
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000350
Tony Lowndsf53dec22002-12-20 04:24:43 +0000351 def build_subprocess_arglist(self):
Tony Lownds2398d572003-05-13 15:28:21 +0000352 w = ['-W' + s for s in sys.warnoptions]
Georg Brandld0761532006-10-12 07:57:21 +0000353 if 1/2 > 0: # account for new division
354 w.append('-Qnew')
Tony Lownds2398d572003-05-13 15:28:21 +0000355 # Maybe IDLE is installed and is being accessed via sys.path,
356 # or maybe it's not installed and the idle.py script is being
357 # run from the IDLE source directory.
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000358 del_exitf = idleConf.GetOption('main', 'General', 'delete-exitfunc',
359 default=False, type='bool')
Tony Lownds2398d572003-05-13 15:28:21 +0000360 if __name__ == 'idlelib.PyShell':
Walter Dörwald70a6b492004-02-12 17:35:32 +0000361 command = "__import__('idlelib.run').run.main(%r)" % (del_exitf,)
Tony Lowndsf2324b92002-09-29 00:34:10 +0000362 else:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000363 command = "__import__('run').main(%r)" % (del_exitf,)
Kurt B. Kaiserb7855182003-08-14 14:54:28 +0000364 if sys.platform[:3] == 'win' and ' ' in sys.executable:
365 # handle embedded space in path by quoting the argument
366 decorated_exec = '"%s"' % sys.executable
367 else:
368 decorated_exec = sys.executable
369 return [decorated_exec] + w + ["-c", command, str(self.port)]
Tony Lowndsf2324b92002-09-29 00:34:10 +0000370
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000371 def start_subprocess(self):
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000372 # spawning first avoids passing a listening socket to the subprocess
373 self.spawn_subprocess()
374 #time.sleep(20) # test to simulate GUI not accepting connection
Kurt B. Kaiser24d7e0c2003-06-05 23:51:29 +0000375 addr = (LOCALHOST, self.port)
Kurt B. Kaiser8dcdb772002-08-05 03:52:10 +0000376 # Idle starts listening for connection on localhost
Kurt B. Kaiser5db48432003-05-15 03:40:51 +0000377 for i in range(3):
Chui Tey5d2af632002-05-26 13:36:41 +0000378 time.sleep(i)
379 try:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000380 self.rpcclt = MyRPCClient(addr)
Chui Tey5d2af632002-05-26 13:36:41 +0000381 break
382 except socket.error, err:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000383 pass
Chui Tey5d2af632002-05-26 13:36:41 +0000384 else:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000385 self.display_port_binding_error()
386 return None
Kurt B. Kaiserb4179362002-07-26 00:06:42 +0000387 # Accept the connection from the Python execution server
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000388 self.rpcclt.listening_sock.settimeout(10)
389 try:
390 self.rpcclt.accept()
391 except socket.timeout, err:
392 self.display_no_subprocess_error()
393 return None
Kurt B. Kaiser969de452002-06-12 03:28:57 +0000394 self.rpcclt.register("stdin", self.tkconsole)
395 self.rpcclt.register("stdout", self.tkconsole.stdout)
396 self.rpcclt.register("stderr", self.tkconsole.stderr)
Chui Tey5d2af632002-05-26 13:36:41 +0000397 self.rpcclt.register("flist", self.tkconsole.flist)
Kurt B. Kaiser8cd0def2003-01-31 05:06:43 +0000398 self.rpcclt.register("linecache", linecache)
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000399 self.rpcclt.register("interp", self)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000400 self.transfer_path()
Chui Tey5d2af632002-05-26 13:36:41 +0000401 self.poll_subprocess()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000402 return self.rpcclt
Chui Tey5d2af632002-05-26 13:36:41 +0000403
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000404 def restart_subprocess(self):
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000405 if self.restarting:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000406 return self.rpcclt
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000407 self.restarting = True
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000408 # close only the subprocess debugger
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000409 debug = self.getdebugger()
410 if debug:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000411 try:
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000412 # Only close subprocess debugger, don't unregister gui_adap!
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000413 RemoteDebugger.close_subprocess_debugger(self.rpcclt)
414 except:
415 pass
416 # Kill subprocess, spawn a new one, accept connection.
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000417 self.rpcclt.close()
418 self.unix_terminate()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000419 console = self.tkconsole
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000420 was_executing = console.executing
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000421 console.executing = False
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000422 self.spawn_subprocess()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000423 try:
424 self.rpcclt.accept()
425 except socket.timeout, err:
426 self.display_no_subprocess_error()
427 return None
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000428 self.transfer_path()
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000429 # annotate restart in shell window and mark it
Kurt B. Kaiser4cc5ef52003-01-22 00:23:23 +0000430 console.text.delete("iomark", "end-1c")
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000431 if was_executing:
432 console.write('\n')
433 console.showprompt()
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000434 halfbar = ((int(console.width) - 16) // 2) * '='
435 console.write(halfbar + ' RESTART ' + halfbar)
436 console.text.mark_set("restart", "end-1c")
437 console.text.mark_gravity("restart", "left")
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000438 console.showprompt()
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000439 # restart subprocess debugger
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000440 if debug:
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000441 # Restarted debugger connects to current instance of debug GUI
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000442 gui = RemoteDebugger.restart_subprocess_debugger(self.rpcclt)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000443 # reload remote debugger breakpoints for all PyShellEditWindows
444 debug.load_breakpoints()
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000445 self.restarting = False
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000446 return self.rpcclt
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000447
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000448 def __request_interrupt(self):
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000449 self.rpcclt.remotecall("exec", "interrupt_the_server", (), {})
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000450
451 def interrupt_subprocess(self):
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000452 threading.Thread(target=self.__request_interrupt).start()
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000453
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000454 def kill_subprocess(self):
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000455 try:
456 self.rpcclt.close()
457 except AttributeError: # no socket
458 pass
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000459 self.unix_terminate()
460 self.tkconsole.executing = False
461 self.rpcclt = None
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000462
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000463 def unix_terminate(self):
464 "UNIX: make sure subprocess is terminated and collect status"
465 if hasattr(os, 'kill'):
466 try:
467 os.kill(self.rpcpid, SIGTERM)
468 except OSError:
469 # process already terminated:
470 return
471 else:
472 try:
473 os.waitpid(self.rpcpid, 0)
474 except OSError:
475 return
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000476
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000477 def transfer_path(self):
478 self.runcommand("""if 1:
479 import sys as _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +0000480 _sys.path = %r
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000481 del _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +0000482 \n""" % (sys.path,))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000483
Chui Tey5d2af632002-05-26 13:36:41 +0000484 active_seq = None
485
486 def poll_subprocess(self):
487 clt = self.rpcclt
488 if clt is None:
489 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000490 try:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000491 response = clt.pollresponse(self.active_seq, wait=0.05)
492 except (EOFError, IOError, KeyboardInterrupt):
493 # lost connection or subprocess terminated itself, restart
494 # [the KBI is from rpc.SocketIO.handle_EOF()]
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000495 if self.tkconsole.closing:
496 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000497 response = None
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000498 self.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000499 if response:
500 self.tkconsole.resetoutput()
501 self.active_seq = None
502 how, what = response
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000503 console = self.tkconsole.console
Chui Tey5d2af632002-05-26 13:36:41 +0000504 if how == "OK":
505 if what is not None:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000506 print >>console, repr(what)
Chui Tey5d2af632002-05-26 13:36:41 +0000507 elif how == "EXCEPTION":
Chui Tey5d2af632002-05-26 13:36:41 +0000508 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
509 self.remote_stack_viewer()
510 elif how == "ERROR":
Kurt B. Kaiser0930c432002-12-06 21:45:24 +0000511 errmsg = "PyShell.ModifiedInterpreter: Subprocess ERROR:\n"
512 print >>sys.__stderr__, errmsg, what
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000513 print >>console, errmsg, what
514 # we received a response to the currently active seq number:
Kurt B. Kaiserd112bc72006-08-16 05:01:42 +0000515 try:
516 self.tkconsole.endexecuting()
517 except AttributeError: # shell may have closed
518 pass
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000519 # Reschedule myself
520 if not self.tkconsole.closing:
521 self.tkconsole.text.after(self.tkconsole.pollinterval,
522 self.poll_subprocess)
Chui Tey5d2af632002-05-26 13:36:41 +0000523
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000524 debugger = None
525
526 def setdebugger(self, debugger):
527 self.debugger = debugger
528
529 def getdebugger(self):
530 return self.debugger
531
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000532 def open_remote_stack_viewer(self):
533 """Initiate the remote stack viewer from a separate thread.
534
535 This method is called from the subprocess, and by returning from this
536 method we allow the subprocess to unblock. After a bit the shell
537 requests the subprocess to open the remote stack viewer which returns a
538 static object looking at the last exceptiopn. It is queried through
539 the RPC mechanism.
540
541 """
542 self.tkconsole.text.after(300, self.remote_stack_viewer)
543 return
544
Chui Tey5d2af632002-05-26 13:36:41 +0000545 def remote_stack_viewer(self):
546 import RemoteObjectBrowser
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000547 oid = self.rpcclt.remotequeue("exec", "stackviewer", ("flist",), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000548 if oid is None:
549 self.tkconsole.root.bell()
550 return
551 item = RemoteObjectBrowser.StubObjectTreeItem(self.rpcclt, oid)
552 from TreeWidget import ScrolledCanvas, TreeNode
553 top = Toplevel(self.tkconsole.root)
Kurt B. Kaiser73360a32004-03-08 18:15:31 +0000554 theme = idleConf.GetOption('main','Theme','name')
555 background = idleConf.GetHighlight(theme, 'normal')['background']
556 sc = ScrolledCanvas(top, bg=background, highlightthickness=0)
Chui Tey5d2af632002-05-26 13:36:41 +0000557 sc.frame.pack(expand=1, fill="both")
558 node = TreeNode(sc.canvas, None, item)
559 node.expand()
560 # XXX Should GC the remote tree when closing the window
561
David Scherer7aced172000-08-15 01:13:23 +0000562 gid = 0
563
564 def execsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000565 "Like runsource() but assumes complete exec source"
David Scherer7aced172000-08-15 01:13:23 +0000566 filename = self.stuffsource(source)
567 self.execfile(filename, source)
568
569 def execfile(self, filename, source=None):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000570 "Execute an existing file"
David Scherer7aced172000-08-15 01:13:23 +0000571 if source is None:
572 source = open(filename, "r").read()
573 try:
574 code = compile(source, filename, "exec")
575 except (OverflowError, SyntaxError):
576 self.tkconsole.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000577 tkerr = self.tkconsole.stderr
578 print>>tkerr, '*** Error in script or command!\n'
579 print>>tkerr, 'Traceback (most recent call last):'
David Scherer7aced172000-08-15 01:13:23 +0000580 InteractiveInterpreter.showsyntaxerror(self, filename)
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000581 self.tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000582 else:
583 self.runcode(code)
584
585 def runsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000586 "Extend base class method: Stuff the source in the line cache first"
David Scherer7aced172000-08-15 01:13:23 +0000587 filename = self.stuffsource(source)
588 self.more = 0
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000589 self.save_warnings_filters = warnings.filters[:]
590 warnings.filterwarnings(action="error", category=SyntaxWarning)
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000591 if isinstance(source, types.UnicodeType):
592 import IOBinding
593 try:
594 source = source.encode(IOBinding.encoding)
595 except UnicodeError:
596 self.tkconsole.resetoutput()
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +0000597 self.write("Unsupported characters in input\n")
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000598 return
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000599 try:
Kurt B. Kaiser935ea9a2005-05-10 03:44:24 +0000600 # InteractiveInterpreter.runsource() calls its runcode() method,
601 # which is overridden (see below)
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000602 return InteractiveInterpreter.runsource(self, source, filename)
603 finally:
604 if self.save_warnings_filters is not None:
605 warnings.filters[:] = self.save_warnings_filters
606 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000607
608 def stuffsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000609 "Stuff source in the filename cache"
David Scherer7aced172000-08-15 01:13:23 +0000610 filename = "<pyshell#%d>" % self.gid
611 self.gid = self.gid + 1
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000612 lines = source.split("\n")
David Scherer7aced172000-08-15 01:13:23 +0000613 linecache.cache[filename] = len(source)+1, 0, lines, filename
614 return filename
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000615
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000616 def prepend_syspath(self, filename):
617 "Prepend sys.path with file's directory if not already included"
618 self.runcommand("""if 1:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000619 _filename = %r
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000620 import sys as _sys
621 from os.path import dirname as _dirname
622 _dir = _dirname(_filename)
623 if not _dir in _sys.path:
624 _sys.path.insert(0, _dir)
625 del _filename, _sys, _dirname, _dir
Walter Dörwald70a6b492004-02-12 17:35:32 +0000626 \n""" % (filename,))
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000627
David Scherer7aced172000-08-15 01:13:23 +0000628 def showsyntaxerror(self, filename=None):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000629 """Extend base class method: Add Colorizing
630
631 Color the offending position instead of printing it and pointing at it
632 with a caret.
633
634 """
David Scherer7aced172000-08-15 01:13:23 +0000635 text = self.tkconsole.text
636 stuff = self.unpackerror()
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000637 if stuff:
638 msg, lineno, offset, line = stuff
639 if lineno == 1:
640 pos = "iomark + %d chars" % (offset-1)
641 else:
642 pos = "iomark linestart + %d lines + %d chars" % \
643 (lineno-1, offset-1)
644 text.tag_add("ERROR", pos)
645 text.see(pos)
646 char = text.get(pos)
647 if char and char in IDENTCHARS:
648 text.tag_add("ERROR", pos + " wordstart", pos)
649 self.tkconsole.resetoutput()
650 self.write("SyntaxError: %s\n" % str(msg))
651 else:
David Scherer7aced172000-08-15 01:13:23 +0000652 self.tkconsole.resetoutput()
653 InteractiveInterpreter.showsyntaxerror(self, filename)
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000654 self.tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000655
656 def unpackerror(self):
657 type, value, tb = sys.exc_info()
658 ok = type is SyntaxError
659 if ok:
660 try:
661 msg, (dummy_filename, lineno, offset, line) = value
Kurt B. Kaiserbea57c62003-07-09 04:27:24 +0000662 if not offset:
663 offset = 0
David Scherer7aced172000-08-15 01:13:23 +0000664 except:
665 ok = 0
666 if ok:
667 return msg, lineno, offset, line
668 else:
669 return None
670
671 def showtraceback(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000672 "Extend base class method to reset output properly"
David Scherer7aced172000-08-15 01:13:23 +0000673 self.tkconsole.resetoutput()
674 self.checklinecache()
675 InteractiveInterpreter.showtraceback(self)
Chui Tey5d2af632002-05-26 13:36:41 +0000676 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
677 self.tkconsole.open_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +0000678
679 def checklinecache(self):
680 c = linecache.cache
681 for key in c.keys():
682 if key[:1] + key[-1:] != "<>":
683 del c[key]
684
Chui Tey5d2af632002-05-26 13:36:41 +0000685 def runcommand(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000686 "Run the code without invoking the debugger"
Chui Tey5d2af632002-05-26 13:36:41 +0000687 # The code better not raise an exception!
688 if self.tkconsole.executing:
Neal Norwitzf4c4f112002-11-30 18:49:10 +0000689 self.display_executing_dialog()
Chui Tey5d2af632002-05-26 13:36:41 +0000690 return 0
691 if self.rpcclt:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000692 self.rpcclt.remotequeue("exec", "runcode", (code,), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000693 else:
694 exec code in self.locals
695 return 1
696
David Scherer7aced172000-08-15 01:13:23 +0000697 def runcode(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000698 "Override base class method"
Chui Tey5d2af632002-05-26 13:36:41 +0000699 if self.tkconsole.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000700 self.interp.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000701 self.checklinecache()
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000702 if self.save_warnings_filters is not None:
703 warnings.filters[:] = self.save_warnings_filters
704 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000705 debugger = self.debugger
706 try:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000707 self.tkconsole.beginexecuting()
Kurt B. Kaiserdddeb0e2007-02-06 03:21:40 +0000708 if not debugger and self.rpcclt is not None:
709 self.active_seq = self.rpcclt.asyncqueue("exec", "runcode",
710 (code,), {})
711 elif debugger:
712 debugger.run(code, self.locals)
713 else:
714 exec code in self.locals
715 except SystemExit:
716 if not self.tkconsole.closing:
717 if tkMessageBox.askyesno(
718 "Exit?",
719 "Do you want to exit altogether?",
720 default="yes",
721 master=self.tkconsole.text):
Kurt B. Kaiserf137e1d2006-08-16 07:04:17 +0000722 raise
Kurt B. Kaiserdddeb0e2007-02-06 03:21:40 +0000723 else:
724 self.showtraceback()
725 else:
726 raise
727 except:
728 if use_subprocess:
729 print >>self.tkconsole.stderr, \
730 "IDLE internal error in runcode()"
David Scherer7aced172000-08-15 01:13:23 +0000731 self.showtraceback()
Kurt B. Kaiserdddeb0e2007-02-06 03:21:40 +0000732 self.tkconsole.endexecuting()
733 else:
734 if self.tkconsole.canceled:
735 self.tkconsole.canceled = False
736 print >>self.tkconsole.stderr, "KeyboardInterrupt"
737 else:
738 self.showtraceback()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000739 finally:
740 if not use_subprocess:
Kurt B. Kaiserd112bc72006-08-16 05:01:42 +0000741 try:
742 self.tkconsole.endexecuting()
743 except AttributeError: # shell may have closed
744 pass
David Scherer7aced172000-08-15 01:13:23 +0000745
746 def write(self, s):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000747 "Override base class method"
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000748 self.tkconsole.stderr.write(s)
David Scherer7aced172000-08-15 01:13:23 +0000749
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000750 def display_port_binding_error(self):
751 tkMessageBox.showerror(
752 "Port Binding Error",
753 "IDLE can't bind TCP/IP port 8833, which is necessary to "
754 "communicate with its Python execution server. Either "
755 "no networking is installed on this computer or another "
756 "process (another IDLE?) is using the port. Run IDLE with the -n "
757 "command line switch to start without a subprocess and refer to "
758 "Help/IDLE Help 'Running without a subprocess' for further "
759 "details.",
760 master=self.tkconsole.text)
761
762 def display_no_subprocess_error(self):
763 tkMessageBox.showerror(
764 "Subprocess Startup Error",
765 "IDLE's subprocess didn't make connection. Either IDLE can't "
766 "start a subprocess or personal firewall software is blocking "
767 "the connection.",
768 master=self.tkconsole.text)
769
770 def display_executing_dialog(self):
771 tkMessageBox.showerror(
772 "Already executing",
773 "The Python Shell window is already executing a command; "
774 "please wait until it is finished.",
775 master=self.tkconsole.text)
776
777
David Scherer7aced172000-08-15 01:13:23 +0000778class PyShell(OutputWindow):
779
780 shell_title = "Python Shell"
781
782 # Override classes
783 ColorDelegator = ModifiedColorDelegator
784 UndoDelegator = ModifiedUndoDelegator
785
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000786 # Override menus
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000787 menu_specs = [
788 ("file", "_File"),
789 ("edit", "_Edit"),
Kurt B. Kaiser4cc5ef52003-01-22 00:23:23 +0000790 ("debug", "_Debug"),
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000791 ("options", "_Options"),
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000792 ("windows", "_Windows"),
793 ("help", "_Help"),
794 ]
David Scherer7aced172000-08-15 01:13:23 +0000795
Ronald Oussoren19302d92006-06-11 14:33:36 +0000796 if macosxSupport.runningAsOSXApp():
797 del menu_specs[-3]
798 menu_specs[-2] = ("windows", "_Window")
799
800
David Scherer7aced172000-08-15 01:13:23 +0000801 # New classes
802 from IdleHistory import History
803
804 def __init__(self, flist=None):
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000805 if use_subprocess:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000806 ms = self.menu_specs
807 if ms[2][0] != "shell":
Kurt B. Kaiser7ae35482006-08-16 21:45:59 +0000808 ms.insert(2, ("shell", "She_ll"))
David Scherer7aced172000-08-15 01:13:23 +0000809 self.interp = ModifiedInterpreter(self)
810 if flist is None:
811 root = Tk()
812 fixwordbreaks(root)
813 root.withdraw()
814 flist = PyShellFileList(root)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000815 #
David Scherer7aced172000-08-15 01:13:23 +0000816 OutputWindow.__init__(self, flist, None, None)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000817 #
Kurt B. Kaiser6af44982005-01-19 00:22:59 +0000818## self.config(usetabs=1, indentwidth=8, context_use_ps1=1)
819 self.usetabs = True
820 # indentwidth must be 8 when using tabs. See note in EditorWindow:
821 self.indentwidth = 8
822 self.context_use_ps1 = True
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000823 #
David Scherer7aced172000-08-15 01:13:23 +0000824 text = self.text
825 text.configure(wrap="char")
826 text.bind("<<newline-and-indent>>", self.enter_callback)
827 text.bind("<<plain-newline-and-indent>>", self.linefeed_callback)
828 text.bind("<<interrupt-execution>>", self.cancel_callback)
829 text.bind("<<beginning-of-line>>", self.home_callback)
830 text.bind("<<end-of-file>>", self.eof_callback)
831 text.bind("<<open-stack-viewer>>", self.open_stack_viewer)
Kurt B. Kaiser57bfe5d2003-05-10 00:09:52 +0000832 text.bind("<<toggle-debugger>>", self.toggle_debugger)
David Scherer7aced172000-08-15 01:13:23 +0000833 text.bind("<<toggle-jit-stack-viewer>>", self.toggle_jit_stack_viewer)
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000834 if use_subprocess:
835 text.bind("<<view-restart>>", self.view_restart_mark)
836 text.bind("<<restart-shell>>", self.restart_shell)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000837 #
David Scherer7aced172000-08-15 01:13:23 +0000838 self.save_stdout = sys.stdout
839 self.save_stderr = sys.stderr
840 self.save_stdin = sys.stdin
Martin v. Löwisbcc651a2003-06-22 07:52:56 +0000841 import IOBinding
842 self.stdout = PseudoFile(self, "stdout", IOBinding.encoding)
843 self.stderr = PseudoFile(self, "stderr", IOBinding.encoding)
844 self.console = PseudoFile(self, "console", IOBinding.encoding)
Chui Tey5d2af632002-05-26 13:36:41 +0000845 if not use_subprocess:
846 sys.stdout = self.stdout
847 sys.stderr = self.stderr
848 sys.stdin = self
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000849 #
David Scherer7aced172000-08-15 01:13:23 +0000850 self.history = self.History(self.text)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000851 #
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000852 self.pollinterval = 50 # millisec
Chui Tey5d2af632002-05-26 13:36:41 +0000853
Kurt B. Kaiser4d5bc602004-06-06 01:29:22 +0000854 def get_standard_extension_names(self):
855 return idleConf.GetExtensions(shell_only=True)
856
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000857 reading = False
858 executing = False
859 canceled = False
860 endoffile = False
861 closing = False
David Scherer7aced172000-08-15 01:13:23 +0000862
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +0000863 def set_warning_stream(self, stream):
Skip Montanarod9161422004-07-06 21:53:27 +0000864 global warning_stream
865 warning_stream = stream
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +0000866
867 def get_warning_stream(self):
868 return warning_stream
869
David Scherer7aced172000-08-15 01:13:23 +0000870 def toggle_debugger(self, event=None):
871 if self.executing:
872 tkMessageBox.showerror("Don't debug now",
873 "You can only toggle the debugger when idle",
874 master=self.text)
875 self.set_debugger_indicator()
876 return "break"
877 else:
878 db = self.interp.getdebugger()
879 if db:
880 self.close_debugger()
881 else:
882 self.open_debugger()
883
884 def set_debugger_indicator(self):
885 db = self.interp.getdebugger()
886 self.setvar("<<toggle-debugger>>", not not db)
887
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000888 def toggle_jit_stack_viewer(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +0000889 pass # All we need is the variable
890
891 def close_debugger(self):
892 db = self.interp.getdebugger()
893 if db:
894 self.interp.setdebugger(None)
895 db.close()
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000896 if self.interp.rpcclt:
897 RemoteDebugger.close_remote_debugger(self.interp.rpcclt)
David Scherer7aced172000-08-15 01:13:23 +0000898 self.resetoutput()
899 self.console.write("[DEBUG OFF]\n")
900 sys.ps1 = ">>> "
901 self.showprompt()
902 self.set_debugger_indicator()
903
904 def open_debugger(self):
Chui Tey5d2af632002-05-26 13:36:41 +0000905 if self.interp.rpcclt:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000906 dbg_gui = RemoteDebugger.start_remote_debugger(self.interp.rpcclt,
907 self)
908 else:
909 dbg_gui = Debugger.Debugger(self)
910 self.interp.setdebugger(dbg_gui)
911 dbg_gui.load_breakpoints()
Chui Tey5d2af632002-05-26 13:36:41 +0000912 sys.ps1 = "[DEBUG ON]\n>>> "
913 self.showprompt()
914 self.set_debugger_indicator()
915
David Scherer7aced172000-08-15 01:13:23 +0000916 def beginexecuting(self):
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000917 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +0000918 self.resetoutput()
919 self.executing = 1
David Scherer7aced172000-08-15 01:13:23 +0000920
921 def endexecuting(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000922 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +0000923 self.executing = 0
924 self.canceled = 0
Chui Tey5d2af632002-05-26 13:36:41 +0000925 self.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000926
927 def close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000928 "Extend EditorWindow.close()"
David Scherer7aced172000-08-15 01:13:23 +0000929 if self.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000930 response = tkMessageBox.askokcancel(
David Scherer7aced172000-08-15 01:13:23 +0000931 "Kill?",
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000932 "The program is still running!\n Do you want to kill it?",
David Scherer7aced172000-08-15 01:13:23 +0000933 default="ok",
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000934 parent=self.text)
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000935 if response == False:
David Scherer7aced172000-08-15 01:13:23 +0000936 return "cancel"
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +0000937 if self.reading:
938 self.top.quit()
939 self.canceled = True
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000940 self.closing = True
941 # Wait for poll_subprocess() rescheduling to stop
942 self.text.after(2 * self.pollinterval, self.close2)
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000943
944 def close2(self):
945 return EditorWindow.close(self)
David Scherer7aced172000-08-15 01:13:23 +0000946
947 def _close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000948 "Extend EditorWindow._close(), shut down debugger and execution server"
David Scherer7aced172000-08-15 01:13:23 +0000949 self.close_debugger()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000950 if use_subprocess:
951 self.interp.kill_subprocess()
David Scherer7aced172000-08-15 01:13:23 +0000952 # Restore std streams
953 sys.stdout = self.save_stdout
954 sys.stderr = self.save_stderr
955 sys.stdin = self.save_stdin
956 # Break cycles
957 self.interp = None
958 self.console = None
David Scherer7aced172000-08-15 01:13:23 +0000959 self.flist.pyshell = None
960 self.history = None
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000961 EditorWindow._close(self)
David Scherer7aced172000-08-15 01:13:23 +0000962
963 def ispythonsource(self, filename):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000964 "Override EditorWindow method: never remove the colorizer"
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000965 return True
David Scherer7aced172000-08-15 01:13:23 +0000966
967 def short_title(self):
968 return self.shell_title
969
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000970 COPYRIGHT = \
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000971 'Type "copyright", "credits" or "license()" for more information.'
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000972
Kurt B. Kaiser220fecf2003-07-27 03:24:19 +0000973 firewallmessage = """
974 ****************************************************************
975 Personal firewall software may warn about the connection IDLE
976 makes to its subprocess using this computer's internal loopback
977 interface. This connection is not visible on any external
978 interface and no data is sent to or received from the Internet.
979 ****************************************************************
980 """
981
David Scherer7aced172000-08-15 01:13:23 +0000982 def begin(self):
983 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000984 if use_subprocess:
985 nosub = ''
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000986 client = self.interp.start_subprocess()
987 if not client:
988 self.close()
Kurt B. Kaiser76637292004-01-21 22:10:01 +0000989 return False
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000990 else:
991 nosub = "==== No Subprocess ===="
Kurt B. Kaiser220fecf2003-07-27 03:24:19 +0000992 self.write("Python %s on %s\n%s\n%s\nIDLE %s %s\n" %
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000993 (sys.version, sys.platform, self.COPYRIGHT,
Kurt B. Kaiser220fecf2003-07-27 03:24:19 +0000994 self.firewallmessage, idlever.IDLE_VERSION, nosub))
David Scherer7aced172000-08-15 01:13:23 +0000995 self.showprompt()
996 import Tkinter
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000997 Tkinter._default_root = None # 03Jan04 KBK What's this?
Kurt B. Kaiser76637292004-01-21 22:10:01 +0000998 return True
David Scherer7aced172000-08-15 01:13:23 +0000999
1000 def readline(self):
1001 save = self.reading
1002 try:
1003 self.reading = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001004 self.top.mainloop() # nested mainloop()
David Scherer7aced172000-08-15 01:13:23 +00001005 finally:
1006 self.reading = save
1007 line = self.text.get("iomark", "end-1c")
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001008 if len(line) == 0: # may be EOF if we quit our mainloop with Ctrl-C
1009 line = "\n"
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001010 if isinstance(line, unicode):
1011 import IOBinding
1012 try:
1013 line = line.encode(IOBinding.encoding)
1014 except UnicodeError:
1015 pass
David Scherer7aced172000-08-15 01:13:23 +00001016 self.resetoutput()
1017 if self.canceled:
1018 self.canceled = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001019 if not use_subprocess:
1020 raise KeyboardInterrupt
David Scherer7aced172000-08-15 01:13:23 +00001021 if self.endoffile:
1022 self.endoffile = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001023 line = ""
David Scherer7aced172000-08-15 01:13:23 +00001024 return line
1025
1026 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001027 return True
David Scherer7aced172000-08-15 01:13:23 +00001028
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001029 def cancel_callback(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +00001030 try:
1031 if self.text.compare("sel.first", "!=", "sel.last"):
1032 return # Active selection -- always use default binding
1033 except:
1034 pass
1035 if not (self.executing or self.reading):
1036 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001037 self.interp.write("KeyboardInterrupt\n")
David Scherer7aced172000-08-15 01:13:23 +00001038 self.showprompt()
1039 return "break"
1040 self.endoffile = 0
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001041 self.canceled = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001042 if (self.executing and self.interp.rpcclt):
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +00001043 if self.interp.getdebugger():
1044 self.interp.restart_subprocess()
1045 else:
1046 self.interp.interrupt_subprocess()
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001047 if self.reading:
1048 self.top.quit() # exit the nested mainloop() in readline()
David Scherer7aced172000-08-15 01:13:23 +00001049 return "break"
1050
1051 def eof_callback(self, event):
1052 if self.executing and not self.reading:
1053 return # Let the default binding (delete next char) take over
1054 if not (self.text.compare("iomark", "==", "insert") and
1055 self.text.compare("insert", "==", "end-1c")):
1056 return # Let the default binding (delete next char) take over
1057 if not self.executing:
David Scherer7aced172000-08-15 01:13:23 +00001058 self.resetoutput()
1059 self.close()
1060 else:
1061 self.canceled = 0
1062 self.endoffile = 1
1063 self.top.quit()
1064 return "break"
1065
1066 def home_callback(self, event):
1067 if event.state != 0 and event.keysym == "Home":
1068 return # <Modifier-Home>; fall back to class binding
1069 if self.text.compare("iomark", "<=", "insert") and \
1070 self.text.compare("insert linestart", "<=", "iomark"):
1071 self.text.mark_set("insert", "iomark")
1072 self.text.tag_remove("sel", "1.0", "end")
1073 self.text.see("insert")
1074 return "break"
1075
1076 def linefeed_callback(self, event):
1077 # Insert a linefeed without entering anything (still autoindented)
1078 if self.reading:
1079 self.text.insert("insert", "\n")
1080 self.text.see("insert")
1081 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001082 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001083 return "break"
1084
1085 def enter_callback(self, event):
1086 if self.executing and not self.reading:
1087 return # Let the default binding (insert '\n') take over
1088 # If some text is selected, recall the selection
1089 # (but only if this before the I/O mark)
1090 try:
1091 sel = self.text.get("sel.first", "sel.last")
1092 if sel:
1093 if self.text.compare("sel.last", "<=", "iomark"):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001094 self.recall(sel, event)
David Scherer7aced172000-08-15 01:13:23 +00001095 return "break"
1096 except:
1097 pass
1098 # If we're strictly before the line containing iomark, recall
1099 # the current line, less a leading prompt, less leading or
1100 # trailing whitespace
1101 if self.text.compare("insert", "<", "iomark linestart"):
1102 # Check if there's a relevant stdin range -- if so, use it
1103 prev = self.text.tag_prevrange("stdin", "insert")
1104 if prev and self.text.compare("insert", "<", prev[1]):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001105 self.recall(self.text.get(prev[0], prev[1]), event)
David Scherer7aced172000-08-15 01:13:23 +00001106 return "break"
1107 next = self.text.tag_nextrange("stdin", "insert")
1108 if next and self.text.compare("insert lineend", ">=", next[0]):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001109 self.recall(self.text.get(next[0], next[1]), event)
David Scherer7aced172000-08-15 01:13:23 +00001110 return "break"
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001111 # No stdin mark -- just get the current line, less any prompt
Kurt B. Kaiserb1754452005-11-18 22:05:48 +00001112 indices = self.text.tag_nextrange("console", "insert linestart")
1113 if indices and \
1114 self.text.compare(indices[0], "<=", "insert linestart"):
1115 self.recall(self.text.get(indices[1], "insert lineend"), event)
1116 else:
1117 self.recall(self.text.get("insert linestart", "insert lineend"), event)
David Scherer7aced172000-08-15 01:13:23 +00001118 return "break"
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001119 # If we're between the beginning of the line and the iomark, i.e.
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001120 # in the prompt area, move to the end of the prompt
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001121 if self.text.compare("insert", "<", "iomark"):
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001122 self.text.mark_set("insert", "iomark")
David Scherer7aced172000-08-15 01:13:23 +00001123 # If we're in the current input and there's only whitespace
1124 # beyond the cursor, erase that whitespace first
1125 s = self.text.get("insert", "end-1c")
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001126 if s and not s.strip():
David Scherer7aced172000-08-15 01:13:23 +00001127 self.text.delete("insert", "end-1c")
1128 # If we're in the current input before its last line,
1129 # insert a newline right at the insert point
1130 if self.text.compare("insert", "<", "end-1c linestart"):
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001131 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001132 return "break"
1133 # We're in the last line; append a newline and submit it
1134 self.text.mark_set("insert", "end-1c")
1135 if self.reading:
1136 self.text.insert("insert", "\n")
1137 self.text.see("insert")
1138 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001139 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001140 self.text.tag_add("stdin", "iomark", "end-1c")
1141 self.text.update_idletasks()
1142 if self.reading:
1143 self.top.quit() # Break out of recursive mainloop() in raw_input()
1144 else:
1145 self.runit()
1146 return "break"
1147
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001148 def recall(self, s, event):
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001149 # remove leading and trailing empty or whitespace lines
1150 s = re.sub(r'^\s*\n', '' , s)
1151 s = re.sub(r'\n\s*$', '', s)
1152 lines = s.split('\n')
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001153 self.text.undo_block_start()
1154 try:
1155 self.text.tag_remove("sel", "1.0", "end")
1156 self.text.mark_set("insert", "end-1c")
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001157 prefix = self.text.get("insert linestart", "insert")
1158 if prefix.rstrip().endswith(':'):
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001159 self.newline_and_indent_event(event)
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001160 prefix = self.text.get("insert linestart", "insert")
1161 self.text.insert("insert", lines[0].strip())
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001162 if len(lines) > 1:
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001163 orig_base_indent = re.search(r'^([ \t]*)', lines[0]).group(0)
1164 new_base_indent = re.search(r'^([ \t]*)', prefix).group(0)
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001165 for line in lines[1:]:
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001166 if line.startswith(orig_base_indent):
1167 # replace orig base indentation with new indentation
1168 line = new_base_indent + line[len(orig_base_indent):]
1169 self.text.insert('insert', '\n'+line.rstrip())
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001170 finally:
1171 self.text.see("insert")
1172 self.text.undo_block_stop()
David Scherer7aced172000-08-15 01:13:23 +00001173
1174 def runit(self):
1175 line = self.text.get("iomark", "end-1c")
1176 # Strip off last newline and surrounding whitespace.
1177 # (To allow you to hit return twice to end a statement.)
1178 i = len(line)
1179 while i > 0 and line[i-1] in " \t":
1180 i = i-1
1181 if i > 0 and line[i-1] == "\n":
1182 i = i-1
1183 while i > 0 and line[i-1] in " \t":
1184 i = i-1
1185 line = line[:i]
1186 more = self.interp.runsource(line)
David Scherer7aced172000-08-15 01:13:23 +00001187
David Scherer7aced172000-08-15 01:13:23 +00001188 def open_stack_viewer(self, event=None):
Chui Tey5d2af632002-05-26 13:36:41 +00001189 if self.interp.rpcclt:
1190 return self.interp.remote_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +00001191 try:
1192 sys.last_traceback
1193 except:
1194 tkMessageBox.showerror("No stack trace",
1195 "There is no stack trace yet.\n"
1196 "(sys.last_traceback is not defined)",
1197 master=self.text)
1198 return
1199 from StackViewer import StackBrowser
1200 sv = StackBrowser(self.root, self.flist)
1201
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001202 def view_restart_mark(self, event=None):
1203 self.text.see("iomark")
1204 self.text.see("restart")
1205
1206 def restart_shell(self, event=None):
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +00001207 self.interp.restart_subprocess()
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001208
David Scherer7aced172000-08-15 01:13:23 +00001209 def showprompt(self):
1210 self.resetoutput()
1211 try:
1212 s = str(sys.ps1)
1213 except:
1214 s = ""
1215 self.console.write(s)
1216 self.text.mark_set("insert", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001217 self.set_line_and_column()
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +00001218 self.io.reset_undo()
David Scherer7aced172000-08-15 01:13:23 +00001219
1220 def resetoutput(self):
1221 source = self.text.get("iomark", "end-1c")
1222 if self.history:
1223 self.history.history_store(source)
1224 if self.text.get("end-2c") != "\n":
1225 self.text.insert("end-1c", "\n")
1226 self.text.mark_set("iomark", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001227 self.set_line_and_column()
David Scherer7aced172000-08-15 01:13:23 +00001228 sys.stdout.softspace = 0
1229
1230 def write(self, s, tags=()):
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001231 try:
1232 self.text.mark_gravity("iomark", "right")
1233 OutputWindow.write(self, s, tags, "iomark")
1234 self.text.mark_gravity("iomark", "left")
1235 except:
1236 pass
David Scherer7aced172000-08-15 01:13:23 +00001237 if self.canceled:
1238 self.canceled = 0
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001239 if not use_subprocess:
1240 raise KeyboardInterrupt
David Scherer7aced172000-08-15 01:13:23 +00001241
Kurt B. Kaiserdcba6622004-12-21 22:10:32 +00001242class PseudoFile(object):
David Scherer7aced172000-08-15 01:13:23 +00001243
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001244 def __init__(self, shell, tags, encoding=None):
David Scherer7aced172000-08-15 01:13:23 +00001245 self.shell = shell
1246 self.tags = tags
Chui Tey5d2af632002-05-26 13:36:41 +00001247 self.softspace = 0
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001248 self.encoding = encoding
David Scherer7aced172000-08-15 01:13:23 +00001249
1250 def write(self, s):
1251 self.shell.write(s, self.tags)
1252
1253 def writelines(self, l):
1254 map(self.write, l)
1255
1256 def flush(self):
1257 pass
1258
1259 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001260 return True
David Scherer7aced172000-08-15 01:13:23 +00001261
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001262
David Scherer7aced172000-08-15 01:13:23 +00001263usage_msg = """\
David Scherer7aced172000-08-15 01:13:23 +00001264
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001265USAGE: idle [-deins] [-t title] [file]*
1266 idle [-dns] [-t title] (-c cmd | -r file) [arg]*
1267 idle [-dns] [-t title] - [arg]*
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001268
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001269 -h print this help message and exit
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001270 -n run IDLE without a subprocess (see Help/IDLE Help for details)
David Scherer7aced172000-08-15 01:13:23 +00001271
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001272The following options will override the IDLE 'settings' configuration:
Kurt B. Kaiser96d88422001-07-17 04:59:01 +00001273
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001274 -e open an edit window
1275 -i open a shell window
1276
1277The following options imply -i and will open a shell:
1278
1279 -c cmd run the command in a shell, or
1280 -r file run script from file
1281
1282 -d enable the debugger
1283 -s run $IDLESTARTUP or $PYTHONSTARTUP before anything else
1284 -t title set title of shell window
1285
1286A default edit window will be bypassed when -c, -r, or - are used.
1287
1288[arg]* are passed to the command (-c) or script (-r) in sys.argv[1:].
1289
1290Examples:
1291
1292idle
1293 Open an edit window or shell depending on IDLE's configuration.
1294
1295idle foo.py foobar.py
1296 Edit the files, also open a shell if configured to start with shell.
1297
1298idle -est "Baz" foo.py
1299 Run $IDLESTARTUP or $PYTHONSTARTUP, edit foo.py, and open a shell
1300 window with the title "Baz".
1301
1302idle -c "import sys; print sys.argv" "foo"
1303 Open a shell window and run the command, passing "-c" in sys.argv[0]
1304 and "foo" in sys.argv[1].
1305
1306idle -d -s -r foo.py "Hello World"
1307 Open a shell window, run a startup script, enable the debugger, and
1308 run foo.py, passing "foo.py" in sys.argv[0] and "Hello World" in
1309 sys.argv[1].
1310
1311echo "import sys; print sys.argv" | idle - "foobar"
1312 Open a shell window, run the script piped in, passing '' in sys.argv[0]
1313 and "foobar" in sys.argv[1].
David Scherer7aced172000-08-15 01:13:23 +00001314"""
1315
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001316def main():
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001317 global flist, root, use_subprocess
David Scherer7aced172000-08-15 01:13:23 +00001318
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001319 use_subprocess = True
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001320 enable_shell = False
1321 enable_edit = False
1322 debug = False
1323 cmd = None
1324 script = None
1325 startup = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001326 try:
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001327 opts, args = getopt.getopt(sys.argv[1:], "c:deihnr:st:")
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001328 except getopt.error, msg:
1329 sys.stderr.write("Error: %s\n" % str(msg))
1330 sys.stderr.write(usage_msg)
1331 sys.exit(2)
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001332 for o, a in opts:
1333 if o == '-c':
1334 cmd = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001335 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001336 if o == '-d':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001337 debug = True
1338 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001339 if o == '-e':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001340 enable_edit = True
1341 if o == '-h':
1342 sys.stdout.write(usage_msg)
1343 sys.exit()
1344 if o == '-i':
1345 enable_shell = True
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001346 if o == '-n':
1347 use_subprocess = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001348 if o == '-r':
1349 script = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001350 if os.path.isfile(script):
1351 pass
1352 else:
1353 print "No script file: ", script
1354 sys.exit()
1355 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001356 if o == '-s':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001357 startup = True
1358 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001359 if o == '-t':
1360 PyShell.shell_title = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001361 enable_shell = True
1362 if args and args[0] == '-':
1363 cmd = sys.stdin.read()
1364 enable_shell = True
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001365 # process sys.argv and sys.path:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001366 for i in range(len(sys.path)):
1367 sys.path[i] = os.path.abspath(sys.path[i])
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001368 if args and args[0] == '-':
1369 sys.argv = [''] + args[1:]
1370 elif cmd:
1371 sys.argv = ['-c'] + args
1372 elif script:
1373 sys.argv = [script] + args
1374 elif args:
1375 enable_edit = True
1376 pathx = []
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001377 for filename in args:
1378 pathx.append(os.path.dirname(filename))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001379 for dir in pathx:
1380 dir = os.path.abspath(dir)
1381 if not dir in sys.path:
1382 sys.path.insert(0, dir)
Kurt B. Kaiserff002b92002-12-21 21:39:11 +00001383 else:
1384 dir = os.getcwd()
1385 if not dir in sys.path:
1386 sys.path.insert(0, dir)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001387 # check the IDLE settings configuration (but command line overrides)
1388 edit_start = idleConf.GetOption('main', 'General',
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001389 'editor-on-startup', type='bool')
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001390 enable_edit = enable_edit or edit_start
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001391 enable_shell = enable_shell or not edit_start
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001392 # start editor and/or shell windows:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001393 root = Tk(className="Idle")
Ronald Oussoren19302d92006-06-11 14:33:36 +00001394
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001395 fixwordbreaks(root)
1396 root.withdraw()
1397 flist = PyShellFileList(root)
Ronald Oussoren19302d92006-06-11 14:33:36 +00001398 macosxSupport.setupApp(root, flist)
1399
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001400 if enable_edit:
1401 if not (cmd or script):
1402 for filename in args:
1403 flist.open(filename)
1404 if not args:
1405 flist.new()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001406 if enable_shell:
Ronald Oussoren19302d92006-06-11 14:33:36 +00001407 shell = flist.open_shell()
1408 if not shell:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001409 return # couldn't open shell
Ronald Oussoren19302d92006-06-11 14:33:36 +00001410
1411 if macosxSupport.runningAsOSXApp() and flist.dict:
1412 # On OSX: when the user has double-clicked on a file that causes
Tim Peters4f96f1f2006-06-11 19:42:51 +00001413 # IDLE to be launched the shell window will open just in front of
1414 # the file she wants to see. Lower the interpreter window when
Ronald Oussoren19302d92006-06-11 14:33:36 +00001415 # there are open files.
1416 shell.top.lower()
1417
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001418 shell = flist.pyshell
1419 # handle remaining options:
1420 if debug:
1421 shell.open_debugger()
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001422 if startup:
1423 filename = os.environ.get("IDLESTARTUP") or \
1424 os.environ.get("PYTHONSTARTUP")
1425 if filename and os.path.isfile(filename):
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001426 shell.interp.execfile(filename)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001427 if shell and cmd or script:
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001428 shell.interp.runcommand("""if 1:
1429 import sys as _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001430 _sys.argv = %r
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001431 del _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001432 \n""" % (sys.argv,))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001433 if cmd:
1434 shell.interp.execsource(cmd)
1435 elif script:
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001436 shell.interp.prepend_syspath(script)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001437 shell.interp.execfile(script)
Ronald Oussoren19302d92006-06-11 14:33:36 +00001438
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001439 root.mainloop()
1440 root.destroy()
1441
David Scherer7aced172000-08-15 01:13:23 +00001442if __name__ == "__main__":
Kurt B. Kaiser9e8b8282003-06-15 17:38:45 +00001443 sys.modules['PyShell'] = sys.modules['__main__']
David Scherer7aced172000-08-15 01:13:23 +00001444 main()