blob: a9b8f720bec9103eedb1f9fc5c909cf82c873135 [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
David Scherer7aced172000-08-15 01:13:23 +00006import getopt
7import re
Chui Tey5d2af632002-05-26 13:36:41 +00008import socket
9import time
Kurt B. Kaiser003091c2003-02-17 18:57:16 +000010import threading
Chui Tey5d2af632002-05-26 13:36:41 +000011import traceback
Kurt B. Kaiser62833982002-09-18 17:07:05 +000012import types
David Scherer7aced172000-08-15 01:13:23 +000013
14import linecache
15from code import InteractiveInterpreter
16
Kurt B. Kaiser2303b1c2003-11-24 05:26:16 +000017try:
18 from Tkinter import *
19except ImportError:
Guido van Rossumbe19ed72007-02-09 05:37:30 +000020 print("** IDLE can't import Tkinter. " \
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +000021 "Your Python may not be configured for Tk. **", file=sys.__stderr__)
Kurt B. Kaiser2303b1c2003-11-24 05:26:16 +000022 sys.exit(1)
David Scherer7aced172000-08-15 01:13:23 +000023import tkMessageBox
24
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +000025from idlelib.EditorWindow import EditorWindow, fixwordbreaks
26from idlelib.FileList import FileList
27from idlelib.ColorDelegator import ColorDelegator
28from idlelib.UndoDelegator import UndoDelegator
29from idlelib.OutputWindow import OutputWindow
30from idlelib.configHandler import idleConf
31from idlelib import idlever
32from idlelib import rpc
33from idlelib import Debugger
34from idlelib import RemoteDebugger
35from idlelib import macosxSupport
Chui Tey5d2af632002-05-26 13:36:41 +000036
Kurt B. Kaiser24d7e0c2003-06-05 23:51:29 +000037LOCALHOST = '127.0.0.1'
Kurt B. Kaiserb9764192002-09-23 04:10:37 +000038
Kurt B. Kaisera00050f2003-05-08 20:26:55 +000039try:
40 from signal import SIGTERM
41except ImportError:
42 SIGTERM = 15
43
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000044# Override warnings module to write to warning_stream. Initialize to send IDLE
45# internal warnings to the console. ScriptBinding.check_syntax() will
46# temporarily redirect the stream to the shell window to display warnings when
47# checking user's code.
48global warning_stream
49warning_stream = sys.__stderr__
Chui Tey5d2af632002-05-26 13:36:41 +000050try:
51 import warnings
52except ImportError:
53 pass
54else:
55 def idle_showwarning(message, category, filename, lineno):
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000056 file = warning_stream
57 try:
58 file.write(warnings.formatwarning(message, category, filename, lineno))
59 except IOError:
60 pass ## file (probably __stderr__) is invalid, warning dropped.
Chui Tey5d2af632002-05-26 13:36:41 +000061 warnings.showwarning = idle_showwarning
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000062 def idle_formatwarning(message, category, filename, lineno):
63 """Format warnings the IDLE way"""
64 s = "\nWarning (from warnings module):\n"
65 s += ' File \"%s\", line %s\n' % (filename, lineno)
66 line = linecache.getline(filename, lineno).strip()
67 if line:
68 s += " %s\n" % line
69 s += "%s: %s\n>>> " % (category.__name__, message)
70 return s
71 warnings.formatwarning = idle_formatwarning
Chui Tey5d2af632002-05-26 13:36:41 +000072
Kurt B. Kaiserf7a88992004-11-13 21:05:58 +000073def extended_linecache_checkcache(filename=None,
74 orig_checkcache=linecache.checkcache):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +000075 """Extend linecache.checkcache to preserve the <pyshell#...> entries
76
Kurt B. Kaiserf7a88992004-11-13 21:05:58 +000077 Rather than repeating the linecache code, patch it to save the
78 <pyshell#...> entries, call the original linecache.checkcache()
79 (which destroys them), and then restore the saved entries.
80
81 orig_checkcache is bound at definition time to the original
82 method, allowing it to be patched.
Kurt B. Kaiser45186c42002-10-23 04:48:08 +000083
84 """
David Scherer7aced172000-08-15 01:13:23 +000085 cache = linecache.cache
86 save = {}
Kurt B. Kaisere0712772007-08-23 05:25:55 +000087 for filename in cache:
David Scherer7aced172000-08-15 01:13:23 +000088 if filename[:1] + filename[-1:] == '<>':
89 save[filename] = cache[filename]
90 orig_checkcache()
91 cache.update(save)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +000092
Kurt B. Kaiser81885592002-11-29 22:10:53 +000093# Patch linecache.checkcache():
94linecache.checkcache = extended_linecache_checkcache
David Scherer7aced172000-08-15 01:13:23 +000095
Kurt B. Kaiser45186c42002-10-23 04:48:08 +000096
David Scherer7aced172000-08-15 01:13:23 +000097class PyShellEditorWindow(EditorWindow):
Kurt B. Kaiser183403a2004-08-22 05:14:32 +000098 "Regular text edit window in IDLE, supports breakpoints"
Kurt B. Kaiser45186c42002-10-23 04:48:08 +000099
David Scherer7aced172000-08-15 01:13:23 +0000100 def __init__(self, *args):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000101 self.breakpoints = []
Raymond Hettinger931237e2003-07-09 18:48:24 +0000102 EditorWindow.__init__(self, *args)
David Scherer7aced172000-08-15 01:13:23 +0000103 self.text.bind("<<set-breakpoint-here>>", self.set_breakpoint_here)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000104 self.text.bind("<<clear-breakpoint-here>>", self.clear_breakpoint_here)
David Scherer7aced172000-08-15 01:13:23 +0000105 self.text.bind("<<open-python-shell>>", self.flist.open_shell)
106
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000107 self.breakpointPath = os.path.join(idleConf.GetUserCfgDir(),
108 'breakpoints.lst')
Chui Teya2adb0f2002-11-04 22:14:54 +0000109 # whenever a file is changed, restore breakpoints
110 if self.io.filename: self.restore_file_breaks()
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000111 def filename_changed_hook(old_hook=self.io.filename_change_hook,
112 self=self):
Chui Teya2adb0f2002-11-04 22:14:54 +0000113 self.restore_file_breaks()
114 old_hook()
115 self.io.set_filename_change_hook(filename_changed_hook)
116
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000117 rmenu_specs = [("Set Breakpoint", "<<set-breakpoint-here>>"),
118 ("Clear Breakpoint", "<<clear-breakpoint-here>>")]
David Scherer7aced172000-08-15 01:13:23 +0000119
Chui Teya2adb0f2002-11-04 22:14:54 +0000120 def set_breakpoint(self, lineno):
121 text = self.text
122 filename = self.io.filename
123 text.tag_add("BREAK", "%d.0" % lineno, "%d.0" % (lineno+1))
124 try:
125 i = self.breakpoints.index(lineno)
126 except ValueError: # only add if missing, i.e. do once
127 self.breakpoints.append(lineno)
128 try: # update the subprocess debugger
129 debug = self.flist.pyshell.interp.debugger
130 debug.set_breakpoint_here(filename, lineno)
131 except: # but debugger may not be active right now....
132 pass
133
David Scherer7aced172000-08-15 01:13:23 +0000134 def set_breakpoint_here(self, event=None):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000135 text = self.text
136 filename = self.io.filename
137 if not filename:
138 text.bell()
David Scherer7aced172000-08-15 01:13:23 +0000139 return
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000140 lineno = int(float(text.index("insert")))
Chui Teya2adb0f2002-11-04 22:14:54 +0000141 self.set_breakpoint(lineno)
David Scherer7aced172000-08-15 01:13:23 +0000142
Kurt B. Kaiser669f4c32002-06-20 04:01:47 +0000143 def clear_breakpoint_here(self, event=None):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000144 text = self.text
145 filename = self.io.filename
146 if not filename:
147 text.bell()
Kurt B. Kaiser669f4c32002-06-20 04:01:47 +0000148 return
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000149 lineno = int(float(text.index("insert")))
150 try:
151 self.breakpoints.remove(lineno)
152 except:
153 pass
154 text.tag_remove("BREAK", "insert linestart",\
155 "insert lineend +1char")
156 try:
157 debug = self.flist.pyshell.interp.debugger
158 debug.clear_breakpoint_here(filename, lineno)
159 except:
160 pass
161
162 def clear_file_breaks(self):
163 if self.breakpoints:
164 text = self.text
165 filename = self.io.filename
166 if not filename:
167 text.bell()
168 return
169 self.breakpoints = []
170 text.tag_remove("BREAK", "1.0", END)
171 try:
172 debug = self.flist.pyshell.interp.debugger
173 debug.clear_file_breaks(filename)
174 except:
175 pass
176
Chui Teya2adb0f2002-11-04 22:14:54 +0000177 def store_file_breaks(self):
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000178 "Save breakpoints when file is saved"
179 # XXX 13 Dec 2002 KBK Currently the file must be saved before it can
180 # be run. The breaks are saved at that time. If we introduce
181 # a temporary file save feature the save breaks functionality
182 # needs to be re-verified, since the breaks at the time the
183 # temp file is created may differ from the breaks at the last
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000184 # permanent save of the file. Currently, a break introduced
185 # after a save will be effective, but not persistent.
186 # This is necessary to keep the saved breaks synched with the
187 # saved file.
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000188 #
189 # Breakpoints are set as tagged ranges in the text. Certain
190 # kinds of edits cause these ranges to be deleted: Inserting
191 # or deleting a line just before a breakpoint, and certain
192 # deletions prior to a breakpoint. These issues need to be
193 # investigated and understood. It's not clear if they are
194 # Tk issues or IDLE issues, or whether they can actually
195 # be fixed. Since a modified file has to be saved before it is
196 # run, and since self.breakpoints (from which the subprocess
197 # debugger is loaded) is updated during the save, the visible
198 # breaks stay synched with the subprocess even if one of these
199 # unexpected breakpoint deletions occurs.
200 breaks = self.breakpoints
201 filename = self.io.filename
Chui Teya2adb0f2002-11-04 22:14:54 +0000202 try:
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000203 lines = open(self.breakpointPath,"r").readlines()
Chui Teya2adb0f2002-11-04 22:14:54 +0000204 except IOError:
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000205 lines = []
206 new_file = open(self.breakpointPath,"w")
Chui Teya2adb0f2002-11-04 22:14:54 +0000207 for line in lines:
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000208 if not line.startswith(filename + '='):
Chui Teya2adb0f2002-11-04 22:14:54 +0000209 new_file.write(line)
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000210 self.update_breakpoints()
211 breaks = self.breakpoints
212 if breaks:
213 new_file.write(filename + '=' + str(breaks) + '\n')
Chui Teya2adb0f2002-11-04 22:14:54 +0000214 new_file.close()
215
216 def restore_file_breaks(self):
217 self.text.update() # this enables setting "BREAK" tags to be visible
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000218 filename = self.io.filename
219 if filename is None:
220 return
Chui Tey69371d62002-11-04 23:39:45 +0000221 if os.path.isfile(self.breakpointPath):
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000222 lines = open(self.breakpointPath,"r").readlines()
Chui Tey69371d62002-11-04 23:39:45 +0000223 for line in lines:
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000224 if line.startswith(filename + '='):
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000225 breakpoint_linenumbers = eval(line[len(filename)+1:])
Chui Tey69371d62002-11-04 23:39:45 +0000226 for breakpoint_linenumber in breakpoint_linenumbers:
227 self.set_breakpoint(breakpoint_linenumber)
Chui Teya2adb0f2002-11-04 22:14:54 +0000228
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000229 def update_breakpoints(self):
230 "Retrieves all the breakpoints in the current window"
Chui Teya2adb0f2002-11-04 22:14:54 +0000231 text = self.text
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000232 ranges = text.tag_ranges("BREAK")
233 linenumber_list = self.ranges_to_linenumbers(ranges)
234 self.breakpoints = linenumber_list
235
236 def ranges_to_linenumbers(self, ranges):
237 lines = []
238 for index in range(0, len(ranges), 2):
239 lineno = int(float(ranges[index]))
240 end = int(float(ranges[index+1]))
241 while lineno < end:
242 lines.append(lineno)
243 lineno += 1
244 return lines
245
Kurt B. Kaiser11220fa2002-12-24 00:57:22 +0000246# XXX 13 Dec 2002 KBK Not used currently
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000247# def saved_change_hook(self):
248# "Extend base method - clear breaks if module is modified"
249# if not self.get_saved():
250# self.clear_file_breaks()
251# EditorWindow.saved_change_hook(self)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000252
253 def _close(self):
254 "Extend base method - clear breaks when module is closed"
255 self.clear_file_breaks()
256 EditorWindow._close(self)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000257
David Scherer7aced172000-08-15 01:13:23 +0000258
259class PyShellFileList(FileList):
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000260 "Extend base class: IDLE supports a shell and breakpoints"
David Scherer7aced172000-08-15 01:13:23 +0000261
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000262 # override FileList's class variable, instances return PyShellEditorWindow
263 # instead of EditorWindow when new edit windows are created.
David Scherer7aced172000-08-15 01:13:23 +0000264 EditorWindow = PyShellEditorWindow
265
266 pyshell = None
267
268 def open_shell(self, event=None):
269 if self.pyshell:
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000270 self.pyshell.top.wakeup()
David Scherer7aced172000-08-15 01:13:23 +0000271 else:
272 self.pyshell = PyShell(self)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000273 if self.pyshell:
274 if not self.pyshell.begin():
275 return None
David Scherer7aced172000-08-15 01:13:23 +0000276 return self.pyshell
277
278
279class ModifiedColorDelegator(ColorDelegator):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000280 "Extend base class: colorizer for the shell window itself"
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000281
Steven M. Gavab77d3432002-03-02 07:16:21 +0000282 def __init__(self):
283 ColorDelegator.__init__(self)
284 self.LoadTagDefs()
David Scherer7aced172000-08-15 01:13:23 +0000285
286 def recolorize_main(self):
287 self.tag_remove("TODO", "1.0", "iomark")
288 self.tag_add("SYNC", "1.0", "iomark")
289 ColorDelegator.recolorize_main(self)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000290
Steven M. Gavab77d3432002-03-02 07:16:21 +0000291 def LoadTagDefs(self):
292 ColorDelegator.LoadTagDefs(self)
293 theme = idleConf.GetOption('main','Theme','name')
294 self.tagdefs.update({
295 "stdin": {'background':None,'foreground':None},
296 "stdout": idleConf.GetHighlight(theme, "stdout"),
297 "stderr": idleConf.GetHighlight(theme, "stderr"),
298 "console": idleConf.GetHighlight(theme, "console"),
Kurt B. Kaiser6ae6ba02007-08-10 19:45:35 +0000299 ### KBK 10Aug07: None tag doesn't seem to serve a purpose and
300 ### breaks in py3k. Comment out for now.
301 #None: idleConf.GetHighlight(theme, "normal"),
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]
353 # Maybe IDLE is installed and is being accessed via sys.path,
354 # or maybe it's not installed and the idle.py script is being
355 # run from the IDLE source directory.
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000356 del_exitf = idleConf.GetOption('main', 'General', 'delete-exitfunc',
357 default=False, type='bool')
Tony Lownds2398d572003-05-13 15:28:21 +0000358 if __name__ == 'idlelib.PyShell':
Walter Dörwald70a6b492004-02-12 17:35:32 +0000359 command = "__import__('idlelib.run').run.main(%r)" % (del_exitf,)
Tony Lowndsf2324b92002-09-29 00:34:10 +0000360 else:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000361 command = "__import__('run').main(%r)" % (del_exitf,)
Kurt B. Kaiserb7855182003-08-14 14:54:28 +0000362 if sys.platform[:3] == 'win' and ' ' in sys.executable:
363 # handle embedded space in path by quoting the argument
364 decorated_exec = '"%s"' % sys.executable
365 else:
366 decorated_exec = sys.executable
367 return [decorated_exec] + w + ["-c", command, str(self.port)]
Tony Lowndsf2324b92002-09-29 00:34:10 +0000368
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000369 def start_subprocess(self):
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000370 # spawning first avoids passing a listening socket to the subprocess
371 self.spawn_subprocess()
372 #time.sleep(20) # test to simulate GUI not accepting connection
Kurt B. Kaiser24d7e0c2003-06-05 23:51:29 +0000373 addr = (LOCALHOST, self.port)
Kurt B. Kaiser8dcdb772002-08-05 03:52:10 +0000374 # Idle starts listening for connection on localhost
Kurt B. Kaiser5db48432003-05-15 03:40:51 +0000375 for i in range(3):
Chui Tey5d2af632002-05-26 13:36:41 +0000376 time.sleep(i)
377 try:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000378 self.rpcclt = MyRPCClient(addr)
Chui Tey5d2af632002-05-26 13:36:41 +0000379 break
Guido van Rossumb940e112007-01-10 16:19:56 +0000380 except socket.error as err:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000381 pass
Chui Tey5d2af632002-05-26 13:36:41 +0000382 else:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000383 self.display_port_binding_error()
384 return None
Kurt B. Kaiserb4179362002-07-26 00:06:42 +0000385 # Accept the connection from the Python execution server
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000386 self.rpcclt.listening_sock.settimeout(10)
387 try:
388 self.rpcclt.accept()
Guido van Rossumb940e112007-01-10 16:19:56 +0000389 except socket.timeout as err:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000390 self.display_no_subprocess_error()
391 return None
Kurt B. Kaiser969de452002-06-12 03:28:57 +0000392 self.rpcclt.register("stdin", self.tkconsole)
393 self.rpcclt.register("stdout", self.tkconsole.stdout)
394 self.rpcclt.register("stderr", self.tkconsole.stderr)
Chui Tey5d2af632002-05-26 13:36:41 +0000395 self.rpcclt.register("flist", self.tkconsole.flist)
Kurt B. Kaiser8cd0def2003-01-31 05:06:43 +0000396 self.rpcclt.register("linecache", linecache)
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000397 self.rpcclt.register("interp", self)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000398 self.transfer_path()
Chui Tey5d2af632002-05-26 13:36:41 +0000399 self.poll_subprocess()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000400 return self.rpcclt
Chui Tey5d2af632002-05-26 13:36:41 +0000401
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000402 def restart_subprocess(self):
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000403 if self.restarting:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000404 return self.rpcclt
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000405 self.restarting = True
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000406 # close only the subprocess debugger
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000407 debug = self.getdebugger()
408 if debug:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000409 try:
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000410 # Only close subprocess debugger, don't unregister gui_adap!
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000411 RemoteDebugger.close_subprocess_debugger(self.rpcclt)
412 except:
413 pass
414 # Kill subprocess, spawn a new one, accept connection.
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000415 self.rpcclt.close()
416 self.unix_terminate()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000417 console = self.tkconsole
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000418 was_executing = console.executing
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000419 console.executing = False
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000420 self.spawn_subprocess()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000421 try:
422 self.rpcclt.accept()
Guido van Rossumb940e112007-01-10 16:19:56 +0000423 except socket.timeout as err:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000424 self.display_no_subprocess_error()
425 return None
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000426 self.transfer_path()
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000427 # annotate restart in shell window and mark it
Kurt B. Kaiser4cc5ef52003-01-22 00:23:23 +0000428 console.text.delete("iomark", "end-1c")
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000429 if was_executing:
430 console.write('\n')
431 console.showprompt()
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000432 halfbar = ((int(console.width) - 16) // 2) * '='
433 console.write(halfbar + ' RESTART ' + halfbar)
434 console.text.mark_set("restart", "end-1c")
435 console.text.mark_gravity("restart", "left")
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000436 console.showprompt()
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000437 # restart subprocess debugger
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000438 if debug:
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000439 # Restarted debugger connects to current instance of debug GUI
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000440 gui = RemoteDebugger.restart_subprocess_debugger(self.rpcclt)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000441 # reload remote debugger breakpoints for all PyShellEditWindows
442 debug.load_breakpoints()
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000443 self.restarting = False
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000444 return self.rpcclt
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000445
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000446 def __request_interrupt(self):
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000447 self.rpcclt.remotecall("exec", "interrupt_the_server", (), {})
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000448
449 def interrupt_subprocess(self):
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000450 threading.Thread(target=self.__request_interrupt).start()
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000451
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000452 def kill_subprocess(self):
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000453 try:
454 self.rpcclt.close()
455 except AttributeError: # no socket
456 pass
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000457 self.unix_terminate()
458 self.tkconsole.executing = False
459 self.rpcclt = None
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000460
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000461 def unix_terminate(self):
462 "UNIX: make sure subprocess is terminated and collect status"
463 if hasattr(os, 'kill'):
464 try:
465 os.kill(self.rpcpid, SIGTERM)
466 except OSError:
467 # process already terminated:
468 return
469 else:
470 try:
471 os.waitpid(self.rpcpid, 0)
472 except OSError:
473 return
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000474
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000475 def transfer_path(self):
476 self.runcommand("""if 1:
477 import sys as _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +0000478 _sys.path = %r
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000479 del _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +0000480 \n""" % (sys.path,))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000481
Chui Tey5d2af632002-05-26 13:36:41 +0000482 active_seq = None
483
484 def poll_subprocess(self):
485 clt = self.rpcclt
486 if clt is None:
487 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000488 try:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000489 response = clt.pollresponse(self.active_seq, wait=0.05)
490 except (EOFError, IOError, KeyboardInterrupt):
491 # lost connection or subprocess terminated itself, restart
492 # [the KBI is from rpc.SocketIO.handle_EOF()]
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000493 if self.tkconsole.closing:
494 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000495 response = None
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000496 self.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000497 if response:
498 self.tkconsole.resetoutput()
499 self.active_seq = None
500 how, what = response
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000501 console = self.tkconsole.console
Chui Tey5d2af632002-05-26 13:36:41 +0000502 if how == "OK":
503 if what is not None:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000504 print(repr(what), file=console)
Chui Tey5d2af632002-05-26 13:36:41 +0000505 elif how == "EXCEPTION":
Chui Tey5d2af632002-05-26 13:36:41 +0000506 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
507 self.remote_stack_viewer()
508 elif how == "ERROR":
Kurt B. Kaiser0930c432002-12-06 21:45:24 +0000509 errmsg = "PyShell.ModifiedInterpreter: Subprocess ERROR:\n"
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000510 print(errmsg, what, file=sys.__stderr__)
511 print(errmsg, what, file=console)
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000512 # we received a response to the currently active seq number:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000513 try:
514 self.tkconsole.endexecuting()
515 except AttributeError: # shell may have closed
516 pass
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000517 # Reschedule myself
518 if not self.tkconsole.closing:
519 self.tkconsole.text.after(self.tkconsole.pollinterval,
520 self.poll_subprocess)
Chui Tey5d2af632002-05-26 13:36:41 +0000521
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000522 debugger = None
523
524 def setdebugger(self, debugger):
525 self.debugger = debugger
526
527 def getdebugger(self):
528 return self.debugger
529
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000530 def open_remote_stack_viewer(self):
531 """Initiate the remote stack viewer from a separate thread.
532
533 This method is called from the subprocess, and by returning from this
534 method we allow the subprocess to unblock. After a bit the shell
535 requests the subprocess to open the remote stack viewer which returns a
536 static object looking at the last exceptiopn. It is queried through
537 the RPC mechanism.
538
539 """
540 self.tkconsole.text.after(300, self.remote_stack_viewer)
541 return
542
Chui Tey5d2af632002-05-26 13:36:41 +0000543 def remote_stack_viewer(self):
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000544 from idlelib import RemoteObjectBrowser
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000545 oid = self.rpcclt.remotequeue("exec", "stackviewer", ("flist",), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000546 if oid is None:
547 self.tkconsole.root.bell()
548 return
549 item = RemoteObjectBrowser.StubObjectTreeItem(self.rpcclt, oid)
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000550 from idlelib.TreeWidget import ScrolledCanvas, TreeNode
Chui Tey5d2af632002-05-26 13:36:41 +0000551 top = Toplevel(self.tkconsole.root)
Kurt B. Kaiser73360a32004-03-08 18:15:31 +0000552 theme = idleConf.GetOption('main','Theme','name')
553 background = idleConf.GetHighlight(theme, 'normal')['background']
554 sc = ScrolledCanvas(top, bg=background, highlightthickness=0)
Chui Tey5d2af632002-05-26 13:36:41 +0000555 sc.frame.pack(expand=1, fill="both")
556 node = TreeNode(sc.canvas, None, item)
557 node.expand()
558 # XXX Should GC the remote tree when closing the window
559
David Scherer7aced172000-08-15 01:13:23 +0000560 gid = 0
561
562 def execsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000563 "Like runsource() but assumes complete exec source"
David Scherer7aced172000-08-15 01:13:23 +0000564 filename = self.stuffsource(source)
565 self.execfile(filename, source)
566
567 def execfile(self, filename, source=None):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000568 "Execute an existing file"
David Scherer7aced172000-08-15 01:13:23 +0000569 if source is None:
570 source = open(filename, "r").read()
571 try:
572 code = compile(source, filename, "exec")
573 except (OverflowError, SyntaxError):
574 self.tkconsole.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000575 tkerr = self.tkconsole.stderr
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000576 print('*** Error in script or command!\n', file=tkerr)
577 print('Traceback (most recent call last):', file=tkerr)
David Scherer7aced172000-08-15 01:13:23 +0000578 InteractiveInterpreter.showsyntaxerror(self, filename)
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000579 self.tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000580 else:
581 self.runcode(code)
582
583 def runsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000584 "Extend base class method: Stuff the source in the line cache first"
David Scherer7aced172000-08-15 01:13:23 +0000585 filename = self.stuffsource(source)
586 self.more = 0
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000587 self.save_warnings_filters = warnings.filters[:]
588 warnings.filterwarnings(action="error", category=SyntaxWarning)
Martin v. Löwis98ff8982007-08-13 06:03:15 +0000589 # at the moment, InteractiveInterpreter expects str
590 assert isinstance(source, str)
591 #if isinstance(source, str):
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000592 # from idlelib import IOBinding
Martin v. Löwis98ff8982007-08-13 06:03:15 +0000593 # try:
594 # source = source.encode(IOBinding.encoding)
595 # except UnicodeError:
596 # self.tkconsole.resetoutput()
597 # self.write("Unsupported characters in input\n")
598 # 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):
Guido van Rossum33d26892007-08-05 15:29:28 +0000629 """Override Interactive Interpreter method: Use Colorizing
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000630
631 Color the offending position instead of printing it and pointing at it
632 with a caret.
633
634 """
Guido van Rossum33d26892007-08-05 15:29:28 +0000635 tkconsole = self.tkconsole
636 text = tkconsole.text
637 text.tag_remove("ERROR", "1.0", "end")
David Scherer7aced172000-08-15 01:13:23 +0000638 type, value, tb = sys.exc_info()
Guido van Rossum33d26892007-08-05 15:29:28 +0000639 msg = value.msg or "<no detail available>"
640 lineno = value.lineno or 1
641 offset = value.offset or 0
642 if offset == 0:
643 lineno += 1 #mark end of offending line
644 if lineno == 1:
645 pos = "iomark + %d chars" % (offset-1)
David Scherer7aced172000-08-15 01:13:23 +0000646 else:
Guido van Rossum33d26892007-08-05 15:29:28 +0000647 pos = "iomark linestart + %d lines + %d chars" % \
648 (lineno-1, offset-1)
649 tkconsole.colorize_syntax_error(text, pos)
650 tkconsole.resetoutput()
651 self.write("SyntaxError: %s\n" % msg)
652 tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000653
654 def showtraceback(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000655 "Extend base class method to reset output properly"
David Scherer7aced172000-08-15 01:13:23 +0000656 self.tkconsole.resetoutput()
657 self.checklinecache()
658 InteractiveInterpreter.showtraceback(self)
Chui Tey5d2af632002-05-26 13:36:41 +0000659 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
660 self.tkconsole.open_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +0000661
662 def checklinecache(self):
663 c = linecache.cache
Guido van Rossum36e0a922007-07-20 04:05:57 +0000664 for key in list(c.keys()):
David Scherer7aced172000-08-15 01:13:23 +0000665 if key[:1] + key[-1:] != "<>":
666 del c[key]
667
Chui Tey5d2af632002-05-26 13:36:41 +0000668 def runcommand(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000669 "Run the code without invoking the debugger"
Chui Tey5d2af632002-05-26 13:36:41 +0000670 # The code better not raise an exception!
671 if self.tkconsole.executing:
Neal Norwitzf4c4f112002-11-30 18:49:10 +0000672 self.display_executing_dialog()
Chui Tey5d2af632002-05-26 13:36:41 +0000673 return 0
674 if self.rpcclt:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000675 self.rpcclt.remotequeue("exec", "runcode", (code,), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000676 else:
Georg Brandl7cae87c2006-09-06 06:51:57 +0000677 exec(code, self.locals)
Chui Tey5d2af632002-05-26 13:36:41 +0000678 return 1
679
David Scherer7aced172000-08-15 01:13:23 +0000680 def runcode(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000681 "Override base class method"
Chui Tey5d2af632002-05-26 13:36:41 +0000682 if self.tkconsole.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000683 self.interp.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000684 self.checklinecache()
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000685 if self.save_warnings_filters is not None:
686 warnings.filters[:] = self.save_warnings_filters
687 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000688 debugger = self.debugger
689 try:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000690 self.tkconsole.beginexecuting()
Thomas Wouterscf297e42007-02-23 15:07:44 +0000691 if not debugger and self.rpcclt is not None:
692 self.active_seq = self.rpcclt.asyncqueue("exec", "runcode",
693 (code,), {})
694 elif debugger:
695 debugger.run(code, self.locals)
696 else:
697 exec(code, self.locals)
698 except SystemExit:
699 if not self.tkconsole.closing:
700 if tkMessageBox.askyesno(
701 "Exit?",
702 "Do you want to exit altogether?",
703 default="yes",
704 master=self.tkconsole.text):
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000705 raise
Thomas Wouterscf297e42007-02-23 15:07:44 +0000706 else:
Guido van Rossum5dc0d972007-02-25 22:37:36 +0000707 self.showtraceback()
Thomas Wouterscf297e42007-02-23 15:07:44 +0000708 else:
709 raise
710 except:
711 if use_subprocess:
712 print("IDLE internal error in runcode()",
713 file=self.tkconsole.stderr)
David Scherer7aced172000-08-15 01:13:23 +0000714 self.showtraceback()
Thomas Wouterscf297e42007-02-23 15:07:44 +0000715 self.tkconsole.endexecuting()
716 else:
717 if self.tkconsole.canceled:
718 self.tkconsole.canceled = False
719 print("KeyboardInterrupt", file=self.tkconsole.stderr)
720 else:
721 self.showtraceback()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000722 finally:
723 if not use_subprocess:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000724 try:
725 self.tkconsole.endexecuting()
726 except AttributeError: # shell may have closed
727 pass
David Scherer7aced172000-08-15 01:13:23 +0000728
729 def write(self, s):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000730 "Override base class method"
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000731 self.tkconsole.stderr.write(s)
David Scherer7aced172000-08-15 01:13:23 +0000732
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000733 def display_port_binding_error(self):
734 tkMessageBox.showerror(
735 "Port Binding Error",
736 "IDLE can't bind TCP/IP port 8833, which is necessary to "
737 "communicate with its Python execution server. Either "
738 "no networking is installed on this computer or another "
739 "process (another IDLE?) is using the port. Run IDLE with the -n "
740 "command line switch to start without a subprocess and refer to "
741 "Help/IDLE Help 'Running without a subprocess' for further "
742 "details.",
743 master=self.tkconsole.text)
744
745 def display_no_subprocess_error(self):
746 tkMessageBox.showerror(
747 "Subprocess Startup Error",
748 "IDLE's subprocess didn't make connection. Either IDLE can't "
749 "start a subprocess or personal firewall software is blocking "
750 "the connection.",
751 master=self.tkconsole.text)
752
753 def display_executing_dialog(self):
754 tkMessageBox.showerror(
755 "Already executing",
756 "The Python Shell window is already executing a command; "
757 "please wait until it is finished.",
758 master=self.tkconsole.text)
759
760
David Scherer7aced172000-08-15 01:13:23 +0000761class PyShell(OutputWindow):
762
763 shell_title = "Python Shell"
764
765 # Override classes
766 ColorDelegator = ModifiedColorDelegator
767 UndoDelegator = ModifiedUndoDelegator
768
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000769 # Override menus
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000770 menu_specs = [
771 ("file", "_File"),
772 ("edit", "_Edit"),
Kurt B. Kaiser4cc5ef52003-01-22 00:23:23 +0000773 ("debug", "_Debug"),
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000774 ("options", "_Options"),
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000775 ("windows", "_Windows"),
776 ("help", "_Help"),
777 ]
David Scherer7aced172000-08-15 01:13:23 +0000778
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000779 if macosxSupport.runningAsOSXApp():
780 del menu_specs[-3]
781 menu_specs[-2] = ("windows", "_Window")
782
783
David Scherer7aced172000-08-15 01:13:23 +0000784 # New classes
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000785 from idlelib.IdleHistory import History
David Scherer7aced172000-08-15 01:13:23 +0000786
787 def __init__(self, flist=None):
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000788 if use_subprocess:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000789 ms = self.menu_specs
790 if ms[2][0] != "shell":
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000791 ms.insert(2, ("shell", "She_ll"))
David Scherer7aced172000-08-15 01:13:23 +0000792 self.interp = ModifiedInterpreter(self)
793 if flist is None:
794 root = Tk()
795 fixwordbreaks(root)
796 root.withdraw()
797 flist = PyShellFileList(root)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000798 #
David Scherer7aced172000-08-15 01:13:23 +0000799 OutputWindow.__init__(self, flist, None, None)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000800 #
Kurt B. Kaiser6af44982005-01-19 00:22:59 +0000801## self.config(usetabs=1, indentwidth=8, context_use_ps1=1)
802 self.usetabs = True
803 # indentwidth must be 8 when using tabs. See note in EditorWindow:
804 self.indentwidth = 8
805 self.context_use_ps1 = True
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000806 #
David Scherer7aced172000-08-15 01:13:23 +0000807 text = self.text
808 text.configure(wrap="char")
809 text.bind("<<newline-and-indent>>", self.enter_callback)
810 text.bind("<<plain-newline-and-indent>>", self.linefeed_callback)
811 text.bind("<<interrupt-execution>>", self.cancel_callback)
812 text.bind("<<beginning-of-line>>", self.home_callback)
813 text.bind("<<end-of-file>>", self.eof_callback)
814 text.bind("<<open-stack-viewer>>", self.open_stack_viewer)
Kurt B. Kaiser57bfe5d2003-05-10 00:09:52 +0000815 text.bind("<<toggle-debugger>>", self.toggle_debugger)
David Scherer7aced172000-08-15 01:13:23 +0000816 text.bind("<<toggle-jit-stack-viewer>>", self.toggle_jit_stack_viewer)
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000817 if use_subprocess:
818 text.bind("<<view-restart>>", self.view_restart_mark)
819 text.bind("<<restart-shell>>", self.restart_shell)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000820 #
David Scherer7aced172000-08-15 01:13:23 +0000821 self.save_stdout = sys.stdout
822 self.save_stderr = sys.stderr
823 self.save_stdin = sys.stdin
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000824 from idlelib import IOBinding
Martin v. Löwisbcc651a2003-06-22 07:52:56 +0000825 self.stdout = PseudoFile(self, "stdout", IOBinding.encoding)
826 self.stderr = PseudoFile(self, "stderr", IOBinding.encoding)
827 self.console = PseudoFile(self, "console", IOBinding.encoding)
Chui Tey5d2af632002-05-26 13:36:41 +0000828 if not use_subprocess:
829 sys.stdout = self.stdout
Kurt B. Kaisercbbe98f2007-08-12 01:52:35 +0000830### sys.stderr = self.stderr # Don't redirect exceptions, pyshell NG
Chui Tey5d2af632002-05-26 13:36:41 +0000831 sys.stdin = self
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000832 #
David Scherer7aced172000-08-15 01:13:23 +0000833 self.history = self.History(self.text)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000834 #
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000835 self.pollinterval = 50 # millisec
Chui Tey5d2af632002-05-26 13:36:41 +0000836
Kurt B. Kaiser4d5bc602004-06-06 01:29:22 +0000837 def get_standard_extension_names(self):
838 return idleConf.GetExtensions(shell_only=True)
839
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000840 reading = False
841 executing = False
842 canceled = False
843 endoffile = False
844 closing = False
David Scherer7aced172000-08-15 01:13:23 +0000845
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +0000846 def set_warning_stream(self, stream):
Skip Montanarod9161422004-07-06 21:53:27 +0000847 global warning_stream
848 warning_stream = stream
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +0000849
850 def get_warning_stream(self):
851 return warning_stream
852
David Scherer7aced172000-08-15 01:13:23 +0000853 def toggle_debugger(self, event=None):
854 if self.executing:
855 tkMessageBox.showerror("Don't debug now",
856 "You can only toggle the debugger when idle",
857 master=self.text)
858 self.set_debugger_indicator()
859 return "break"
860 else:
861 db = self.interp.getdebugger()
862 if db:
863 self.close_debugger()
864 else:
865 self.open_debugger()
866
867 def set_debugger_indicator(self):
868 db = self.interp.getdebugger()
869 self.setvar("<<toggle-debugger>>", not not db)
870
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000871 def toggle_jit_stack_viewer(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +0000872 pass # All we need is the variable
873
874 def close_debugger(self):
875 db = self.interp.getdebugger()
876 if db:
877 self.interp.setdebugger(None)
878 db.close()
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000879 if self.interp.rpcclt:
880 RemoteDebugger.close_remote_debugger(self.interp.rpcclt)
David Scherer7aced172000-08-15 01:13:23 +0000881 self.resetoutput()
882 self.console.write("[DEBUG OFF]\n")
883 sys.ps1 = ">>> "
884 self.showprompt()
885 self.set_debugger_indicator()
886
887 def open_debugger(self):
Chui Tey5d2af632002-05-26 13:36:41 +0000888 if self.interp.rpcclt:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000889 dbg_gui = RemoteDebugger.start_remote_debugger(self.interp.rpcclt,
890 self)
891 else:
892 dbg_gui = Debugger.Debugger(self)
893 self.interp.setdebugger(dbg_gui)
894 dbg_gui.load_breakpoints()
Chui Tey5d2af632002-05-26 13:36:41 +0000895 sys.ps1 = "[DEBUG ON]\n>>> "
896 self.showprompt()
897 self.set_debugger_indicator()
898
David Scherer7aced172000-08-15 01:13:23 +0000899 def beginexecuting(self):
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000900 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +0000901 self.resetoutput()
902 self.executing = 1
David Scherer7aced172000-08-15 01:13:23 +0000903
904 def endexecuting(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000905 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +0000906 self.executing = 0
907 self.canceled = 0
Chui Tey5d2af632002-05-26 13:36:41 +0000908 self.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000909
910 def close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000911 "Extend EditorWindow.close()"
David Scherer7aced172000-08-15 01:13:23 +0000912 if self.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000913 response = tkMessageBox.askokcancel(
David Scherer7aced172000-08-15 01:13:23 +0000914 "Kill?",
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000915 "The program is still running!\n Do you want to kill it?",
David Scherer7aced172000-08-15 01:13:23 +0000916 default="ok",
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000917 parent=self.text)
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000918 if response == False:
David Scherer7aced172000-08-15 01:13:23 +0000919 return "cancel"
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +0000920 if self.reading:
921 self.top.quit()
922 self.canceled = True
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000923 self.closing = True
924 # Wait for poll_subprocess() rescheduling to stop
925 self.text.after(2 * self.pollinterval, self.close2)
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000926
927 def close2(self):
928 return EditorWindow.close(self)
David Scherer7aced172000-08-15 01:13:23 +0000929
930 def _close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000931 "Extend EditorWindow._close(), shut down debugger and execution server"
David Scherer7aced172000-08-15 01:13:23 +0000932 self.close_debugger()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000933 if use_subprocess:
934 self.interp.kill_subprocess()
David Scherer7aced172000-08-15 01:13:23 +0000935 # Restore std streams
936 sys.stdout = self.save_stdout
937 sys.stderr = self.save_stderr
938 sys.stdin = self.save_stdin
939 # Break cycles
940 self.interp = None
941 self.console = None
David Scherer7aced172000-08-15 01:13:23 +0000942 self.flist.pyshell = None
943 self.history = None
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000944 EditorWindow._close(self)
David Scherer7aced172000-08-15 01:13:23 +0000945
946 def ispythonsource(self, filename):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000947 "Override EditorWindow method: never remove the colorizer"
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000948 return True
David Scherer7aced172000-08-15 01:13:23 +0000949
950 def short_title(self):
951 return self.shell_title
952
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000953 COPYRIGHT = \
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000954 'Type "copyright", "credits" or "license()" for more information.'
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000955
Kurt B. Kaiser220fecf2003-07-27 03:24:19 +0000956 firewallmessage = """
957 ****************************************************************
958 Personal firewall software may warn about the connection IDLE
959 makes to its subprocess using this computer's internal loopback
960 interface. This connection is not visible on any external
961 interface and no data is sent to or received from the Internet.
962 ****************************************************************
963 """
964
David Scherer7aced172000-08-15 01:13:23 +0000965 def begin(self):
Kurt B. Kaiser7378df72007-08-11 04:20:51 +0000966 self.text.mark_set("iomark", "insert")
David Scherer7aced172000-08-15 01:13:23 +0000967 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000968 if use_subprocess:
969 nosub = ''
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000970 client = self.interp.start_subprocess()
971 if not client:
972 self.close()
Kurt B. Kaiser76637292004-01-21 22:10:01 +0000973 return False
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000974 else:
975 nosub = "==== No Subprocess ===="
Kurt B. Kaiser220fecf2003-07-27 03:24:19 +0000976 self.write("Python %s on %s\n%s\n%s\nIDLE %s %s\n" %
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000977 (sys.version, sys.platform, self.COPYRIGHT,
Kurt B. Kaiser220fecf2003-07-27 03:24:19 +0000978 self.firewallmessage, idlever.IDLE_VERSION, nosub))
David Scherer7aced172000-08-15 01:13:23 +0000979 self.showprompt()
980 import Tkinter
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000981 Tkinter._default_root = None # 03Jan04 KBK What's this?
Kurt B. Kaiser76637292004-01-21 22:10:01 +0000982 return True
David Scherer7aced172000-08-15 01:13:23 +0000983
984 def readline(self):
985 save = self.reading
986 try:
987 self.reading = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +0000988 self.top.mainloop() # nested mainloop()
David Scherer7aced172000-08-15 01:13:23 +0000989 finally:
990 self.reading = save
991 line = self.text.get("iomark", "end-1c")
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +0000992 if len(line) == 0: # may be EOF if we quit our mainloop with Ctrl-C
993 line = "\n"
Guido van Rossumef87d6e2007-05-02 19:09:54 +0000994 if isinstance(line, str):
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000995 from idlelib import IOBinding
Martin v. Löwisbcc651a2003-06-22 07:52:56 +0000996 try:
997 line = line.encode(IOBinding.encoding)
998 except UnicodeError:
999 pass
David Scherer7aced172000-08-15 01:13:23 +00001000 self.resetoutput()
1001 if self.canceled:
1002 self.canceled = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001003 if not use_subprocess:
1004 raise KeyboardInterrupt
David Scherer7aced172000-08-15 01:13:23 +00001005 if self.endoffile:
1006 self.endoffile = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001007 line = ""
David Scherer7aced172000-08-15 01:13:23 +00001008 return line
1009
1010 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001011 return True
David Scherer7aced172000-08-15 01:13:23 +00001012
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001013 def cancel_callback(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +00001014 try:
1015 if self.text.compare("sel.first", "!=", "sel.last"):
1016 return # Active selection -- always use default binding
1017 except:
1018 pass
1019 if not (self.executing or self.reading):
1020 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001021 self.interp.write("KeyboardInterrupt\n")
David Scherer7aced172000-08-15 01:13:23 +00001022 self.showprompt()
1023 return "break"
1024 self.endoffile = 0
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001025 self.canceled = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001026 if (self.executing and self.interp.rpcclt):
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +00001027 if self.interp.getdebugger():
1028 self.interp.restart_subprocess()
1029 else:
1030 self.interp.interrupt_subprocess()
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001031 if self.reading:
1032 self.top.quit() # exit the nested mainloop() in readline()
David Scherer7aced172000-08-15 01:13:23 +00001033 return "break"
1034
1035 def eof_callback(self, event):
1036 if self.executing and not self.reading:
1037 return # Let the default binding (delete next char) take over
1038 if not (self.text.compare("iomark", "==", "insert") and
1039 self.text.compare("insert", "==", "end-1c")):
1040 return # Let the default binding (delete next char) take over
1041 if not self.executing:
David Scherer7aced172000-08-15 01:13:23 +00001042 self.resetoutput()
1043 self.close()
1044 else:
1045 self.canceled = 0
1046 self.endoffile = 1
1047 self.top.quit()
1048 return "break"
1049
1050 def home_callback(self, event):
1051 if event.state != 0 and event.keysym == "Home":
1052 return # <Modifier-Home>; fall back to class binding
1053 if self.text.compare("iomark", "<=", "insert") and \
1054 self.text.compare("insert linestart", "<=", "iomark"):
1055 self.text.mark_set("insert", "iomark")
1056 self.text.tag_remove("sel", "1.0", "end")
1057 self.text.see("insert")
1058 return "break"
1059
1060 def linefeed_callback(self, event):
1061 # Insert a linefeed without entering anything (still autoindented)
1062 if self.reading:
1063 self.text.insert("insert", "\n")
1064 self.text.see("insert")
1065 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001066 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001067 return "break"
1068
1069 def enter_callback(self, event):
1070 if self.executing and not self.reading:
1071 return # Let the default binding (insert '\n') take over
1072 # If some text is selected, recall the selection
1073 # (but only if this before the I/O mark)
1074 try:
1075 sel = self.text.get("sel.first", "sel.last")
1076 if sel:
1077 if self.text.compare("sel.last", "<=", "iomark"):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001078 self.recall(sel, event)
David Scherer7aced172000-08-15 01:13:23 +00001079 return "break"
1080 except:
1081 pass
1082 # If we're strictly before the line containing iomark, recall
1083 # the current line, less a leading prompt, less leading or
1084 # trailing whitespace
1085 if self.text.compare("insert", "<", "iomark linestart"):
1086 # Check if there's a relevant stdin range -- if so, use it
1087 prev = self.text.tag_prevrange("stdin", "insert")
1088 if prev and self.text.compare("insert", "<", prev[1]):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001089 self.recall(self.text.get(prev[0], prev[1]), event)
David Scherer7aced172000-08-15 01:13:23 +00001090 return "break"
1091 next = self.text.tag_nextrange("stdin", "insert")
1092 if next and self.text.compare("insert lineend", ">=", next[0]):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001093 self.recall(self.text.get(next[0], next[1]), event)
David Scherer7aced172000-08-15 01:13:23 +00001094 return "break"
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001095 # No stdin mark -- just get the current line, less any prompt
Kurt B. Kaiserb1754452005-11-18 22:05:48 +00001096 indices = self.text.tag_nextrange("console", "insert linestart")
1097 if indices and \
1098 self.text.compare(indices[0], "<=", "insert linestart"):
1099 self.recall(self.text.get(indices[1], "insert lineend"), event)
1100 else:
1101 self.recall(self.text.get("insert linestart", "insert lineend"), event)
David Scherer7aced172000-08-15 01:13:23 +00001102 return "break"
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001103 # If we're between the beginning of the line and the iomark, i.e.
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001104 # in the prompt area, move to the end of the prompt
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001105 if self.text.compare("insert", "<", "iomark"):
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001106 self.text.mark_set("insert", "iomark")
David Scherer7aced172000-08-15 01:13:23 +00001107 # If we're in the current input and there's only whitespace
1108 # beyond the cursor, erase that whitespace first
1109 s = self.text.get("insert", "end-1c")
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001110 if s and not s.strip():
David Scherer7aced172000-08-15 01:13:23 +00001111 self.text.delete("insert", "end-1c")
1112 # If we're in the current input before its last line,
1113 # insert a newline right at the insert point
1114 if self.text.compare("insert", "<", "end-1c linestart"):
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001115 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001116 return "break"
1117 # We're in the last line; append a newline and submit it
1118 self.text.mark_set("insert", "end-1c")
1119 if self.reading:
1120 self.text.insert("insert", "\n")
1121 self.text.see("insert")
1122 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001123 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001124 self.text.tag_add("stdin", "iomark", "end-1c")
1125 self.text.update_idletasks()
1126 if self.reading:
Neal Norwitzce96f692006-03-17 06:49:51 +00001127 self.top.quit() # Break out of recursive mainloop()
David Scherer7aced172000-08-15 01:13:23 +00001128 else:
1129 self.runit()
1130 return "break"
1131
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001132 def recall(self, s, event):
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001133 # remove leading and trailing empty or whitespace lines
1134 s = re.sub(r'^\s*\n', '' , s)
1135 s = re.sub(r'\n\s*$', '', s)
1136 lines = s.split('\n')
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001137 self.text.undo_block_start()
1138 try:
1139 self.text.tag_remove("sel", "1.0", "end")
1140 self.text.mark_set("insert", "end-1c")
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001141 prefix = self.text.get("insert linestart", "insert")
1142 if prefix.rstrip().endswith(':'):
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001143 self.newline_and_indent_event(event)
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001144 prefix = self.text.get("insert linestart", "insert")
1145 self.text.insert("insert", lines[0].strip())
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001146 if len(lines) > 1:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001147 orig_base_indent = re.search(r'^([ \t]*)', lines[0]).group(0)
1148 new_base_indent = re.search(r'^([ \t]*)', prefix).group(0)
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001149 for line in lines[1:]:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001150 if line.startswith(orig_base_indent):
1151 # replace orig base indentation with new indentation
1152 line = new_base_indent + line[len(orig_base_indent):]
1153 self.text.insert('insert', '\n'+line.rstrip())
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001154 finally:
1155 self.text.see("insert")
1156 self.text.undo_block_stop()
David Scherer7aced172000-08-15 01:13:23 +00001157
1158 def runit(self):
1159 line = self.text.get("iomark", "end-1c")
1160 # Strip off last newline and surrounding whitespace.
1161 # (To allow you to hit return twice to end a statement.)
1162 i = len(line)
1163 while i > 0 and line[i-1] in " \t":
1164 i = i-1
1165 if i > 0 and line[i-1] == "\n":
1166 i = i-1
1167 while i > 0 and line[i-1] in " \t":
1168 i = i-1
1169 line = line[:i]
1170 more = self.interp.runsource(line)
David Scherer7aced172000-08-15 01:13:23 +00001171
David Scherer7aced172000-08-15 01:13:23 +00001172 def open_stack_viewer(self, event=None):
Chui Tey5d2af632002-05-26 13:36:41 +00001173 if self.interp.rpcclt:
1174 return self.interp.remote_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +00001175 try:
1176 sys.last_traceback
1177 except:
1178 tkMessageBox.showerror("No stack trace",
1179 "There is no stack trace yet.\n"
1180 "(sys.last_traceback is not defined)",
1181 master=self.text)
1182 return
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +00001183 from idlelib.StackViewer import StackBrowser
David Scherer7aced172000-08-15 01:13:23 +00001184 sv = StackBrowser(self.root, self.flist)
1185
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001186 def view_restart_mark(self, event=None):
1187 self.text.see("iomark")
1188 self.text.see("restart")
1189
1190 def restart_shell(self, event=None):
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +00001191 self.interp.restart_subprocess()
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001192
David Scherer7aced172000-08-15 01:13:23 +00001193 def showprompt(self):
1194 self.resetoutput()
1195 try:
1196 s = str(sys.ps1)
1197 except:
1198 s = ""
1199 self.console.write(s)
1200 self.text.mark_set("insert", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001201 self.set_line_and_column()
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +00001202 self.io.reset_undo()
David Scherer7aced172000-08-15 01:13:23 +00001203
1204 def resetoutput(self):
1205 source = self.text.get("iomark", "end-1c")
1206 if self.history:
1207 self.history.history_store(source)
1208 if self.text.get("end-2c") != "\n":
1209 self.text.insert("end-1c", "\n")
1210 self.text.mark_set("iomark", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001211 self.set_line_and_column()
David Scherer7aced172000-08-15 01:13:23 +00001212
1213 def write(self, s, tags=()):
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001214 try:
1215 self.text.mark_gravity("iomark", "right")
1216 OutputWindow.write(self, s, tags, "iomark")
1217 self.text.mark_gravity("iomark", "left")
1218 except:
Kurt B. Kaisercbbe98f2007-08-12 01:52:35 +00001219 raise ###pass # ### 11Aug07 KBK if we are expecting exceptions
1220 # let's find out what they are and be specific.
David Scherer7aced172000-08-15 01:13:23 +00001221 if self.canceled:
1222 self.canceled = 0
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001223 if not use_subprocess:
1224 raise KeyboardInterrupt
David Scherer7aced172000-08-15 01:13:23 +00001225
Kurt B. Kaiserdcba6622004-12-21 22:10:32 +00001226class PseudoFile(object):
David Scherer7aced172000-08-15 01:13:23 +00001227
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001228 def __init__(self, shell, tags, encoding=None):
David Scherer7aced172000-08-15 01:13:23 +00001229 self.shell = shell
1230 self.tags = tags
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001231 self.encoding = encoding
David Scherer7aced172000-08-15 01:13:23 +00001232
1233 def write(self, s):
1234 self.shell.write(s, self.tags)
1235
Kurt B. Kaiser66aaf742007-08-09 18:00:23 +00001236 def writelines(self, lines):
1237 for line in lines:
1238 self.write(line)
David Scherer7aced172000-08-15 01:13:23 +00001239
1240 def flush(self):
1241 pass
1242
1243 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001244 return True
David Scherer7aced172000-08-15 01:13:23 +00001245
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001246
David Scherer7aced172000-08-15 01:13:23 +00001247usage_msg = """\
David Scherer7aced172000-08-15 01:13:23 +00001248
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001249USAGE: idle [-deins] [-t title] [file]*
1250 idle [-dns] [-t title] (-c cmd | -r file) [arg]*
1251 idle [-dns] [-t title] - [arg]*
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001252
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001253 -h print this help message and exit
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001254 -n run IDLE without a subprocess (see Help/IDLE Help for details)
David Scherer7aced172000-08-15 01:13:23 +00001255
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001256The following options will override the IDLE 'settings' configuration:
Kurt B. Kaiser96d88422001-07-17 04:59:01 +00001257
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001258 -e open an edit window
1259 -i open a shell window
1260
1261The following options imply -i and will open a shell:
1262
1263 -c cmd run the command in a shell, or
1264 -r file run script from file
1265
1266 -d enable the debugger
1267 -s run $IDLESTARTUP or $PYTHONSTARTUP before anything else
1268 -t title set title of shell window
1269
1270A default edit window will be bypassed when -c, -r, or - are used.
1271
1272[arg]* are passed to the command (-c) or script (-r) in sys.argv[1:].
1273
1274Examples:
1275
1276idle
1277 Open an edit window or shell depending on IDLE's configuration.
1278
1279idle foo.py foobar.py
1280 Edit the files, also open a shell if configured to start with shell.
1281
1282idle -est "Baz" foo.py
1283 Run $IDLESTARTUP or $PYTHONSTARTUP, edit foo.py, and open a shell
1284 window with the title "Baz".
1285
1286idle -c "import sys; print sys.argv" "foo"
1287 Open a shell window and run the command, passing "-c" in sys.argv[0]
1288 and "foo" in sys.argv[1].
1289
1290idle -d -s -r foo.py "Hello World"
1291 Open a shell window, run a startup script, enable the debugger, and
1292 run foo.py, passing "foo.py" in sys.argv[0] and "Hello World" in
1293 sys.argv[1].
1294
1295echo "import sys; print sys.argv" | idle - "foobar"
1296 Open a shell window, run the script piped in, passing '' in sys.argv[0]
1297 and "foobar" in sys.argv[1].
David Scherer7aced172000-08-15 01:13:23 +00001298"""
1299
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001300def main():
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001301 global flist, root, use_subprocess
David Scherer7aced172000-08-15 01:13:23 +00001302
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001303 use_subprocess = True
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001304 enable_shell = False
1305 enable_edit = False
1306 debug = False
1307 cmd = None
1308 script = None
1309 startup = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001310 try:
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001311 opts, args = getopt.getopt(sys.argv[1:], "c:deihnr:st:")
Guido van Rossumb940e112007-01-10 16:19:56 +00001312 except getopt.error as msg:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001313 sys.stderr.write("Error: %s\n" % str(msg))
1314 sys.stderr.write(usage_msg)
1315 sys.exit(2)
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001316 for o, a in opts:
1317 if o == '-c':
1318 cmd = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001319 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001320 if o == '-d':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001321 debug = True
1322 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001323 if o == '-e':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001324 enable_edit = True
1325 if o == '-h':
1326 sys.stdout.write(usage_msg)
1327 sys.exit()
1328 if o == '-i':
1329 enable_shell = True
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001330 if o == '-n':
1331 use_subprocess = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001332 if o == '-r':
1333 script = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001334 if os.path.isfile(script):
1335 pass
1336 else:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001337 print("No script file: ", script)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001338 sys.exit()
1339 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001340 if o == '-s':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001341 startup = True
1342 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001343 if o == '-t':
1344 PyShell.shell_title = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001345 enable_shell = True
1346 if args and args[0] == '-':
1347 cmd = sys.stdin.read()
1348 enable_shell = True
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001349 # process sys.argv and sys.path:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001350 for i in range(len(sys.path)):
1351 sys.path[i] = os.path.abspath(sys.path[i])
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001352 if args and args[0] == '-':
1353 sys.argv = [''] + args[1:]
1354 elif cmd:
1355 sys.argv = ['-c'] + args
1356 elif script:
1357 sys.argv = [script] + args
1358 elif args:
1359 enable_edit = True
1360 pathx = []
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001361 for filename in args:
1362 pathx.append(os.path.dirname(filename))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001363 for dir in pathx:
1364 dir = os.path.abspath(dir)
1365 if not dir in sys.path:
1366 sys.path.insert(0, dir)
Kurt B. Kaiserff002b92002-12-21 21:39:11 +00001367 else:
1368 dir = os.getcwd()
1369 if not dir in sys.path:
1370 sys.path.insert(0, dir)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001371 # check the IDLE settings configuration (but command line overrides)
1372 edit_start = idleConf.GetOption('main', 'General',
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001373 'editor-on-startup', type='bool')
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001374 enable_edit = enable_edit or edit_start
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001375 enable_shell = enable_shell or not edit_start
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001376 # start editor and/or shell windows:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001377 root = Tk(className="Idle")
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001378
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001379 fixwordbreaks(root)
1380 root.withdraw()
1381 flist = PyShellFileList(root)
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001382 macosxSupport.setupApp(root, flist)
1383
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001384 if enable_edit:
1385 if not (cmd or script):
1386 for filename in args:
1387 flist.open(filename)
1388 if not args:
1389 flist.new()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001390 if enable_shell:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001391 shell = flist.open_shell()
1392 if not shell:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001393 return # couldn't open shell
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001394
1395 if macosxSupport.runningAsOSXApp() and flist.dict:
1396 # On OSX: when the user has double-clicked on a file that causes
1397 # IDLE to be launched the shell window will open just in front of
1398 # the file she wants to see. Lower the interpreter window when
1399 # there are open files.
1400 shell.top.lower()
1401
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001402 shell = flist.pyshell
1403 # handle remaining options:
1404 if debug:
1405 shell.open_debugger()
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001406 if startup:
1407 filename = os.environ.get("IDLESTARTUP") or \
1408 os.environ.get("PYTHONSTARTUP")
1409 if filename and os.path.isfile(filename):
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001410 shell.interp.execfile(filename)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001411 if shell and cmd or script:
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001412 shell.interp.runcommand("""if 1:
1413 import sys as _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001414 _sys.argv = %r
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001415 del _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001416 \n""" % (sys.argv,))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001417 if cmd:
1418 shell.interp.execsource(cmd)
1419 elif script:
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001420 shell.interp.prepend_syspath(script)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001421 shell.interp.execfile(script)
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001422
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001423 root.mainloop()
1424 root.destroy()
1425
David Scherer7aced172000-08-15 01:13:23 +00001426if __name__ == "__main__":
Kurt B. Kaiser9e8b8282003-06-15 17:38:45 +00001427 sys.modules['PyShell'] = sys.modules['__main__']
David Scherer7aced172000-08-15 01:13:23 +00001428 main()