blob: cca91ad0eb04b8ebdc37f983c28720a741dae0bc [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:
Georg Brandl14fc4272008-05-17 18:39:55 +000018 from tkinter import *
Kurt B. Kaiser2303b1c2003-11-24 05:26:16 +000019except 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)
Georg Brandl14fc4272008-05-17 18:39:55 +000023import tkinter.messagebox as tkMessageBox
David Scherer7aced172000-08-15 01:13:23 +000024
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:
Benjamin Peterson206e3072008-10-19 14:07:49 +000055 def idle_showwarning(message, category, filename, lineno,
56 file=None, line=None):
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000057 file = warning_stream
58 try:
Benjamin Peterson206e3072008-10-19 14:07:49 +000059 file.write(warnings.formatwarning(message, category, filename,\
60 lineno, file=file, line=line))
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000061 except IOError:
62 pass ## file (probably __stderr__) is invalid, warning dropped.
Chui Tey5d2af632002-05-26 13:36:41 +000063 warnings.showwarning = idle_showwarning
Benjamin Peterson206e3072008-10-19 14:07:49 +000064 def idle_formatwarning(message, category, filename, lineno,
65 file=None, line=None):
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000066 """Format warnings the IDLE way"""
67 s = "\nWarning (from warnings module):\n"
68 s += ' File \"%s\", line %s\n' % (filename, lineno)
Benjamin Peterson206e3072008-10-19 14:07:49 +000069 line = linecache.getline(filename, lineno).strip() \
70 if line is None else line
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000071 if line:
72 s += " %s\n" % line
73 s += "%s: %s\n>>> " % (category.__name__, message)
74 return s
75 warnings.formatwarning = idle_formatwarning
Chui Tey5d2af632002-05-26 13:36:41 +000076
Kurt B. Kaiserf7a88992004-11-13 21:05:58 +000077def extended_linecache_checkcache(filename=None,
78 orig_checkcache=linecache.checkcache):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +000079 """Extend linecache.checkcache to preserve the <pyshell#...> entries
80
Kurt B. Kaiserf7a88992004-11-13 21:05:58 +000081 Rather than repeating the linecache code, patch it to save the
82 <pyshell#...> entries, call the original linecache.checkcache()
83 (which destroys them), and then restore the saved entries.
84
85 orig_checkcache is bound at definition time to the original
86 method, allowing it to be patched.
Kurt B. Kaiser45186c42002-10-23 04:48:08 +000087
88 """
David Scherer7aced172000-08-15 01:13:23 +000089 cache = linecache.cache
90 save = {}
Kurt B. Kaisere0712772007-08-23 05:25:55 +000091 for filename in cache:
David Scherer7aced172000-08-15 01:13:23 +000092 if filename[:1] + filename[-1:] == '<>':
93 save[filename] = cache[filename]
94 orig_checkcache()
95 cache.update(save)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +000096
Kurt B. Kaiser81885592002-11-29 22:10:53 +000097# Patch linecache.checkcache():
98linecache.checkcache = extended_linecache_checkcache
David Scherer7aced172000-08-15 01:13:23 +000099
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000100
David Scherer7aced172000-08-15 01:13:23 +0000101class PyShellEditorWindow(EditorWindow):
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000102 "Regular text edit window in IDLE, supports breakpoints"
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000103
David Scherer7aced172000-08-15 01:13:23 +0000104 def __init__(self, *args):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000105 self.breakpoints = []
Raymond Hettinger931237e2003-07-09 18:48:24 +0000106 EditorWindow.__init__(self, *args)
David Scherer7aced172000-08-15 01:13:23 +0000107 self.text.bind("<<set-breakpoint-here>>", self.set_breakpoint_here)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000108 self.text.bind("<<clear-breakpoint-here>>", self.clear_breakpoint_here)
David Scherer7aced172000-08-15 01:13:23 +0000109 self.text.bind("<<open-python-shell>>", self.flist.open_shell)
110
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000111 self.breakpointPath = os.path.join(idleConf.GetUserCfgDir(),
112 'breakpoints.lst')
Chui Teya2adb0f2002-11-04 22:14:54 +0000113 # whenever a file is changed, restore breakpoints
114 if self.io.filename: self.restore_file_breaks()
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000115 def filename_changed_hook(old_hook=self.io.filename_change_hook,
116 self=self):
Chui Teya2adb0f2002-11-04 22:14:54 +0000117 self.restore_file_breaks()
118 old_hook()
119 self.io.set_filename_change_hook(filename_changed_hook)
120
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000121 rmenu_specs = [("Set Breakpoint", "<<set-breakpoint-here>>"),
122 ("Clear Breakpoint", "<<clear-breakpoint-here>>")]
David Scherer7aced172000-08-15 01:13:23 +0000123
Chui Teya2adb0f2002-11-04 22:14:54 +0000124 def set_breakpoint(self, lineno):
125 text = self.text
126 filename = self.io.filename
127 text.tag_add("BREAK", "%d.0" % lineno, "%d.0" % (lineno+1))
128 try:
129 i = self.breakpoints.index(lineno)
130 except ValueError: # only add if missing, i.e. do once
131 self.breakpoints.append(lineno)
132 try: # update the subprocess debugger
133 debug = self.flist.pyshell.interp.debugger
134 debug.set_breakpoint_here(filename, lineno)
135 except: # but debugger may not be active right now....
136 pass
137
David Scherer7aced172000-08-15 01:13:23 +0000138 def set_breakpoint_here(self, event=None):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000139 text = self.text
140 filename = self.io.filename
141 if not filename:
142 text.bell()
David Scherer7aced172000-08-15 01:13:23 +0000143 return
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000144 lineno = int(float(text.index("insert")))
Chui Teya2adb0f2002-11-04 22:14:54 +0000145 self.set_breakpoint(lineno)
David Scherer7aced172000-08-15 01:13:23 +0000146
Kurt B. Kaiser669f4c32002-06-20 04:01:47 +0000147 def clear_breakpoint_here(self, event=None):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000148 text = self.text
149 filename = self.io.filename
150 if not filename:
151 text.bell()
Kurt B. Kaiser669f4c32002-06-20 04:01:47 +0000152 return
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000153 lineno = int(float(text.index("insert")))
154 try:
155 self.breakpoints.remove(lineno)
156 except:
157 pass
158 text.tag_remove("BREAK", "insert linestart",\
159 "insert lineend +1char")
160 try:
161 debug = self.flist.pyshell.interp.debugger
162 debug.clear_breakpoint_here(filename, lineno)
163 except:
164 pass
165
166 def clear_file_breaks(self):
167 if self.breakpoints:
168 text = self.text
169 filename = self.io.filename
170 if not filename:
171 text.bell()
172 return
173 self.breakpoints = []
174 text.tag_remove("BREAK", "1.0", END)
175 try:
176 debug = self.flist.pyshell.interp.debugger
177 debug.clear_file_breaks(filename)
178 except:
179 pass
180
Chui Teya2adb0f2002-11-04 22:14:54 +0000181 def store_file_breaks(self):
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000182 "Save breakpoints when file is saved"
183 # XXX 13 Dec 2002 KBK Currently the file must be saved before it can
184 # be run. The breaks are saved at that time. If we introduce
185 # a temporary file save feature the save breaks functionality
186 # needs to be re-verified, since the breaks at the time the
187 # temp file is created may differ from the breaks at the last
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000188 # permanent save of the file. Currently, a break introduced
189 # after a save will be effective, but not persistent.
190 # This is necessary to keep the saved breaks synched with the
191 # saved file.
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000192 #
193 # Breakpoints are set as tagged ranges in the text. Certain
194 # kinds of edits cause these ranges to be deleted: Inserting
195 # or deleting a line just before a breakpoint, and certain
196 # deletions prior to a breakpoint. These issues need to be
197 # investigated and understood. It's not clear if they are
198 # Tk issues or IDLE issues, or whether they can actually
199 # be fixed. Since a modified file has to be saved before it is
200 # run, and since self.breakpoints (from which the subprocess
201 # debugger is loaded) is updated during the save, the visible
202 # breaks stay synched with the subprocess even if one of these
203 # unexpected breakpoint deletions occurs.
204 breaks = self.breakpoints
205 filename = self.io.filename
Chui Teya2adb0f2002-11-04 22:14:54 +0000206 try:
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000207 lines = open(self.breakpointPath,"r").readlines()
Chui Teya2adb0f2002-11-04 22:14:54 +0000208 except IOError:
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000209 lines = []
210 new_file = open(self.breakpointPath,"w")
Chui Teya2adb0f2002-11-04 22:14:54 +0000211 for line in lines:
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000212 if not line.startswith(filename + '='):
Chui Teya2adb0f2002-11-04 22:14:54 +0000213 new_file.write(line)
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000214 self.update_breakpoints()
215 breaks = self.breakpoints
216 if breaks:
217 new_file.write(filename + '=' + str(breaks) + '\n')
Chui Teya2adb0f2002-11-04 22:14:54 +0000218 new_file.close()
219
220 def restore_file_breaks(self):
221 self.text.update() # this enables setting "BREAK" tags to be visible
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000222 filename = self.io.filename
223 if filename is None:
224 return
Chui Tey69371d62002-11-04 23:39:45 +0000225 if os.path.isfile(self.breakpointPath):
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000226 lines = open(self.breakpointPath,"r").readlines()
Chui Tey69371d62002-11-04 23:39:45 +0000227 for line in lines:
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000228 if line.startswith(filename + '='):
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000229 breakpoint_linenumbers = eval(line[len(filename)+1:])
Chui Tey69371d62002-11-04 23:39:45 +0000230 for breakpoint_linenumber in breakpoint_linenumbers:
231 self.set_breakpoint(breakpoint_linenumber)
Chui Teya2adb0f2002-11-04 22:14:54 +0000232
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000233 def update_breakpoints(self):
234 "Retrieves all the breakpoints in the current window"
Chui Teya2adb0f2002-11-04 22:14:54 +0000235 text = self.text
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000236 ranges = text.tag_ranges("BREAK")
237 linenumber_list = self.ranges_to_linenumbers(ranges)
238 self.breakpoints = linenumber_list
239
240 def ranges_to_linenumbers(self, ranges):
241 lines = []
242 for index in range(0, len(ranges), 2):
243 lineno = int(float(ranges[index]))
244 end = int(float(ranges[index+1]))
245 while lineno < end:
246 lines.append(lineno)
247 lineno += 1
248 return lines
249
Kurt B. Kaiser11220fa2002-12-24 00:57:22 +0000250# XXX 13 Dec 2002 KBK Not used currently
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000251# def saved_change_hook(self):
252# "Extend base method - clear breaks if module is modified"
253# if not self.get_saved():
254# self.clear_file_breaks()
255# EditorWindow.saved_change_hook(self)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000256
257 def _close(self):
258 "Extend base method - clear breaks when module is closed"
259 self.clear_file_breaks()
260 EditorWindow._close(self)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000261
David Scherer7aced172000-08-15 01:13:23 +0000262
263class PyShellFileList(FileList):
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000264 "Extend base class: IDLE supports a shell and breakpoints"
David Scherer7aced172000-08-15 01:13:23 +0000265
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000266 # override FileList's class variable, instances return PyShellEditorWindow
267 # instead of EditorWindow when new edit windows are created.
David Scherer7aced172000-08-15 01:13:23 +0000268 EditorWindow = PyShellEditorWindow
269
270 pyshell = None
271
272 def open_shell(self, event=None):
273 if self.pyshell:
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000274 self.pyshell.top.wakeup()
David Scherer7aced172000-08-15 01:13:23 +0000275 else:
276 self.pyshell = PyShell(self)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000277 if self.pyshell:
278 if not self.pyshell.begin():
279 return None
David Scherer7aced172000-08-15 01:13:23 +0000280 return self.pyshell
281
282
283class ModifiedColorDelegator(ColorDelegator):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000284 "Extend base class: colorizer for the shell window itself"
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000285
Steven M. Gavab77d3432002-03-02 07:16:21 +0000286 def __init__(self):
287 ColorDelegator.__init__(self)
288 self.LoadTagDefs()
David Scherer7aced172000-08-15 01:13:23 +0000289
290 def recolorize_main(self):
291 self.tag_remove("TODO", "1.0", "iomark")
292 self.tag_add("SYNC", "1.0", "iomark")
293 ColorDelegator.recolorize_main(self)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000294
Steven M. Gavab77d3432002-03-02 07:16:21 +0000295 def LoadTagDefs(self):
296 ColorDelegator.LoadTagDefs(self)
297 theme = idleConf.GetOption('main','Theme','name')
298 self.tagdefs.update({
299 "stdin": {'background':None,'foreground':None},
300 "stdout": idleConf.GetHighlight(theme, "stdout"),
301 "stderr": idleConf.GetHighlight(theme, "stderr"),
302 "console": idleConf.GetHighlight(theme, "console"),
Steven M. Gavab77d3432002-03-02 07:16:21 +0000303 })
David Scherer7aced172000-08-15 01:13:23 +0000304
David Scherer7aced172000-08-15 01:13:23 +0000305class ModifiedUndoDelegator(UndoDelegator):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000306 "Extend base class: forbid insert/delete before the I/O mark"
David Scherer7aced172000-08-15 01:13:23 +0000307
308 def insert(self, index, chars, tags=None):
309 try:
310 if self.delegate.compare(index, "<", "iomark"):
311 self.delegate.bell()
312 return
313 except TclError:
314 pass
315 UndoDelegator.insert(self, index, chars, tags)
316
317 def delete(self, index1, index2=None):
318 try:
319 if self.delegate.compare(index1, "<", "iomark"):
320 self.delegate.bell()
321 return
322 except TclError:
323 pass
324 UndoDelegator.delete(self, index1, index2)
325
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000326
327class MyRPCClient(rpc.RPCClient):
328
329 def handle_EOF(self):
330 "Override the base class - just re-raise EOFError"
331 raise EOFError
332
Kurt B. Kaiser8d1f11b2003-05-26 22:20:34 +0000333
David Scherer7aced172000-08-15 01:13:23 +0000334class ModifiedInterpreter(InteractiveInterpreter):
335
336 def __init__(self, tkconsole):
337 self.tkconsole = tkconsole
338 locals = sys.modules['__main__'].__dict__
339 InteractiveInterpreter.__init__(self, locals=locals)
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000340 self.save_warnings_filters = None
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000341 self.restarting = False
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000342 self.subprocess_arglist = self.build_subprocess_arglist()
David Scherer7aced172000-08-15 01:13:23 +0000343
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000344 port = 8833
Chui Tey5d2af632002-05-26 13:36:41 +0000345 rpcclt = None
346 rpcpid = None
347
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000348 def spawn_subprocess(self):
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000349 args = self.subprocess_arglist
Kurt B. Kaiserb7855182003-08-14 14:54:28 +0000350 self.rpcpid = os.spawnv(os.P_NOWAIT, sys.executable, args)
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000351
Tony Lowndsf53dec22002-12-20 04:24:43 +0000352 def build_subprocess_arglist(self):
Tony Lownds2398d572003-05-13 15:28:21 +0000353 w = ['-W' + s for s in sys.warnoptions]
354 # Maybe IDLE is installed and is being accessed via sys.path,
355 # or maybe it's not installed and the idle.py script is being
356 # run from the IDLE source directory.
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000357 del_exitf = idleConf.GetOption('main', 'General', 'delete-exitfunc',
358 default=False, type='bool')
Tony Lownds2398d572003-05-13 15:28:21 +0000359 if __name__ == 'idlelib.PyShell':
Walter Dörwald70a6b492004-02-12 17:35:32 +0000360 command = "__import__('idlelib.run').run.main(%r)" % (del_exitf,)
Tony Lowndsf2324b92002-09-29 00:34:10 +0000361 else:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000362 command = "__import__('run').main(%r)" % (del_exitf,)
Kurt B. Kaiserb7855182003-08-14 14:54:28 +0000363 if sys.platform[:3] == 'win' and ' ' in sys.executable:
364 # handle embedded space in path by quoting the argument
365 decorated_exec = '"%s"' % sys.executable
366 else:
367 decorated_exec = sys.executable
368 return [decorated_exec] + w + ["-c", command, str(self.port)]
Tony Lowndsf2324b92002-09-29 00:34:10 +0000369
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000370 def start_subprocess(self):
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000371 # spawning first avoids passing a listening socket to the subprocess
372 self.spawn_subprocess()
373 #time.sleep(20) # test to simulate GUI not accepting connection
Kurt B. Kaiser24d7e0c2003-06-05 23:51:29 +0000374 addr = (LOCALHOST, self.port)
Kurt B. Kaiser8dcdb772002-08-05 03:52:10 +0000375 # Idle starts listening for connection on localhost
Kurt B. Kaiser5db48432003-05-15 03:40:51 +0000376 for i in range(3):
Chui Tey5d2af632002-05-26 13:36:41 +0000377 time.sleep(i)
378 try:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000379 self.rpcclt = MyRPCClient(addr)
Chui Tey5d2af632002-05-26 13:36:41 +0000380 break
Guido van Rossumb940e112007-01-10 16:19:56 +0000381 except socket.error as err:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000382 pass
Chui Tey5d2af632002-05-26 13:36:41 +0000383 else:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000384 self.display_port_binding_error()
385 return None
Kurt B. Kaiserb4179362002-07-26 00:06:42 +0000386 # Accept the connection from the Python execution server
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000387 self.rpcclt.listening_sock.settimeout(10)
388 try:
389 self.rpcclt.accept()
Guido van Rossumb940e112007-01-10 16:19:56 +0000390 except socket.timeout as err:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000391 self.display_no_subprocess_error()
392 return None
Kurt B. Kaiser969de452002-06-12 03:28:57 +0000393 self.rpcclt.register("stdin", self.tkconsole)
394 self.rpcclt.register("stdout", self.tkconsole.stdout)
395 self.rpcclt.register("stderr", self.tkconsole.stderr)
Chui Tey5d2af632002-05-26 13:36:41 +0000396 self.rpcclt.register("flist", self.tkconsole.flist)
Kurt B. Kaiser8cd0def2003-01-31 05:06:43 +0000397 self.rpcclt.register("linecache", linecache)
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000398 self.rpcclt.register("interp", self)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000399 self.transfer_path()
Chui Tey5d2af632002-05-26 13:36:41 +0000400 self.poll_subprocess()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000401 return self.rpcclt
Chui Tey5d2af632002-05-26 13:36:41 +0000402
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000403 def restart_subprocess(self):
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000404 if self.restarting:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000405 return self.rpcclt
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000406 self.restarting = True
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000407 # close only the subprocess debugger
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000408 debug = self.getdebugger()
409 if debug:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000410 try:
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000411 # Only close subprocess debugger, don't unregister gui_adap!
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000412 RemoteDebugger.close_subprocess_debugger(self.rpcclt)
413 except:
414 pass
415 # Kill subprocess, spawn a new one, accept connection.
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000416 self.rpcclt.close()
417 self.unix_terminate()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000418 console = self.tkconsole
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000419 was_executing = console.executing
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000420 console.executing = False
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000421 self.spawn_subprocess()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000422 try:
423 self.rpcclt.accept()
Guido van Rossumb940e112007-01-10 16:19:56 +0000424 except socket.timeout as err:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000425 self.display_no_subprocess_error()
426 return None
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000427 self.transfer_path()
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000428 # annotate restart in shell window and mark it
Kurt B. Kaiser4cc5ef52003-01-22 00:23:23 +0000429 console.text.delete("iomark", "end-1c")
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000430 if was_executing:
431 console.write('\n')
432 console.showprompt()
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000433 halfbar = ((int(console.width) - 16) // 2) * '='
434 console.write(halfbar + ' RESTART ' + halfbar)
435 console.text.mark_set("restart", "end-1c")
436 console.text.mark_gravity("restart", "left")
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000437 console.showprompt()
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000438 # restart subprocess debugger
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000439 if debug:
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000440 # Restarted debugger connects to current instance of debug GUI
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000441 gui = RemoteDebugger.restart_subprocess_debugger(self.rpcclt)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000442 # reload remote debugger breakpoints for all PyShellEditWindows
443 debug.load_breakpoints()
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000444 self.restarting = False
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000445 return self.rpcclt
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000446
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000447 def __request_interrupt(self):
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000448 self.rpcclt.remotecall("exec", "interrupt_the_server", (), {})
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000449
450 def interrupt_subprocess(self):
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000451 threading.Thread(target=self.__request_interrupt).start()
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000452
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000453 def kill_subprocess(self):
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000454 try:
455 self.rpcclt.close()
456 except AttributeError: # no socket
457 pass
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000458 self.unix_terminate()
459 self.tkconsole.executing = False
460 self.rpcclt = None
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000461
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000462 def unix_terminate(self):
463 "UNIX: make sure subprocess is terminated and collect status"
464 if hasattr(os, 'kill'):
465 try:
466 os.kill(self.rpcpid, SIGTERM)
467 except OSError:
468 # process already terminated:
469 return
470 else:
471 try:
472 os.waitpid(self.rpcpid, 0)
473 except OSError:
474 return
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000475
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000476 def transfer_path(self):
477 self.runcommand("""if 1:
478 import sys as _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +0000479 _sys.path = %r
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000480 del _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +0000481 \n""" % (sys.path,))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000482
Chui Tey5d2af632002-05-26 13:36:41 +0000483 active_seq = None
484
485 def poll_subprocess(self):
486 clt = self.rpcclt
487 if clt is None:
488 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000489 try:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000490 response = clt.pollresponse(self.active_seq, wait=0.05)
491 except (EOFError, IOError, KeyboardInterrupt):
492 # lost connection or subprocess terminated itself, restart
493 # [the KBI is from rpc.SocketIO.handle_EOF()]
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000494 if self.tkconsole.closing:
495 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000496 response = None
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000497 self.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000498 if response:
499 self.tkconsole.resetoutput()
500 self.active_seq = None
501 how, what = response
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000502 console = self.tkconsole.console
Chui Tey5d2af632002-05-26 13:36:41 +0000503 if how == "OK":
504 if what is not None:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000505 print(repr(what), file=console)
Chui Tey5d2af632002-05-26 13:36:41 +0000506 elif how == "EXCEPTION":
Chui Tey5d2af632002-05-26 13:36:41 +0000507 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
508 self.remote_stack_viewer()
509 elif how == "ERROR":
Kurt B. Kaiser0930c432002-12-06 21:45:24 +0000510 errmsg = "PyShell.ModifiedInterpreter: Subprocess ERROR:\n"
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000511 print(errmsg, what, file=sys.__stderr__)
512 print(errmsg, what, file=console)
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000513 # we received a response to the currently active seq number:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000514 try:
515 self.tkconsole.endexecuting()
516 except AttributeError: # shell may have closed
517 pass
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000518 # Reschedule myself
519 if not self.tkconsole.closing:
520 self.tkconsole.text.after(self.tkconsole.pollinterval,
521 self.poll_subprocess)
Chui Tey5d2af632002-05-26 13:36:41 +0000522
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000523 debugger = None
524
525 def setdebugger(self, debugger):
526 self.debugger = debugger
527
528 def getdebugger(self):
529 return self.debugger
530
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000531 def open_remote_stack_viewer(self):
532 """Initiate the remote stack viewer from a separate thread.
533
534 This method is called from the subprocess, and by returning from this
535 method we allow the subprocess to unblock. After a bit the shell
536 requests the subprocess to open the remote stack viewer which returns a
537 static object looking at the last exceptiopn. It is queried through
538 the RPC mechanism.
539
540 """
541 self.tkconsole.text.after(300, self.remote_stack_viewer)
542 return
543
Chui Tey5d2af632002-05-26 13:36:41 +0000544 def remote_stack_viewer(self):
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000545 from idlelib import RemoteObjectBrowser
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000546 oid = self.rpcclt.remotequeue("exec", "stackviewer", ("flist",), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000547 if oid is None:
548 self.tkconsole.root.bell()
549 return
550 item = RemoteObjectBrowser.StubObjectTreeItem(self.rpcclt, oid)
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000551 from idlelib.TreeWidget import ScrolledCanvas, TreeNode
Chui Tey5d2af632002-05-26 13:36:41 +0000552 top = Toplevel(self.tkconsole.root)
Kurt B. Kaiser73360a32004-03-08 18:15:31 +0000553 theme = idleConf.GetOption('main','Theme','name')
554 background = idleConf.GetHighlight(theme, 'normal')['background']
555 sc = ScrolledCanvas(top, bg=background, highlightthickness=0)
Chui Tey5d2af632002-05-26 13:36:41 +0000556 sc.frame.pack(expand=1, fill="both")
557 node = TreeNode(sc.canvas, None, item)
558 node.expand()
559 # XXX Should GC the remote tree when closing the window
560
David Scherer7aced172000-08-15 01:13:23 +0000561 gid = 0
562
563 def execsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000564 "Like runsource() but assumes complete exec source"
David Scherer7aced172000-08-15 01:13:23 +0000565 filename = self.stuffsource(source)
566 self.execfile(filename, source)
567
568 def execfile(self, filename, source=None):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000569 "Execute an existing file"
David Scherer7aced172000-08-15 01:13:23 +0000570 if source is None:
571 source = open(filename, "r").read()
572 try:
573 code = compile(source, filename, "exec")
574 except (OverflowError, SyntaxError):
575 self.tkconsole.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000576 tkerr = self.tkconsole.stderr
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000577 print('*** Error in script or command!\n', file=tkerr)
578 print('Traceback (most recent call last):', file=tkerr)
David Scherer7aced172000-08-15 01:13:23 +0000579 InteractiveInterpreter.showsyntaxerror(self, filename)
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000580 self.tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000581 else:
582 self.runcode(code)
583
584 def runsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000585 "Extend base class method: Stuff the source in the line cache first"
David Scherer7aced172000-08-15 01:13:23 +0000586 filename = self.stuffsource(source)
587 self.more = 0
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000588 self.save_warnings_filters = warnings.filters[:]
589 warnings.filterwarnings(action="error", category=SyntaxWarning)
Martin v. Löwis98ff8982007-08-13 06:03:15 +0000590 # at the moment, InteractiveInterpreter expects str
591 assert isinstance(source, str)
592 #if isinstance(source, str):
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000593 # from idlelib import IOBinding
Martin v. Löwis98ff8982007-08-13 06:03:15 +0000594 # try:
595 # source = source.encode(IOBinding.encoding)
596 # except UnicodeError:
597 # self.tkconsole.resetoutput()
598 # self.write("Unsupported characters in input\n")
599 # return
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000600 try:
Kurt B. Kaiser935ea9a2005-05-10 03:44:24 +0000601 # InteractiveInterpreter.runsource() calls its runcode() method,
602 # which is overridden (see below)
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000603 return InteractiveInterpreter.runsource(self, source, filename)
604 finally:
605 if self.save_warnings_filters is not None:
606 warnings.filters[:] = self.save_warnings_filters
607 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000608
609 def stuffsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000610 "Stuff source in the filename cache"
David Scherer7aced172000-08-15 01:13:23 +0000611 filename = "<pyshell#%d>" % self.gid
612 self.gid = self.gid + 1
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000613 lines = source.split("\n")
David Scherer7aced172000-08-15 01:13:23 +0000614 linecache.cache[filename] = len(source)+1, 0, lines, filename
615 return filename
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000616
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000617 def prepend_syspath(self, filename):
618 "Prepend sys.path with file's directory if not already included"
619 self.runcommand("""if 1:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000620 _filename = %r
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000621 import sys as _sys
622 from os.path import dirname as _dirname
623 _dir = _dirname(_filename)
624 if not _dir in _sys.path:
625 _sys.path.insert(0, _dir)
626 del _filename, _sys, _dirname, _dir
Walter Dörwald70a6b492004-02-12 17:35:32 +0000627 \n""" % (filename,))
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000628
David Scherer7aced172000-08-15 01:13:23 +0000629 def showsyntaxerror(self, filename=None):
Guido van Rossum33d26892007-08-05 15:29:28 +0000630 """Override Interactive Interpreter method: Use Colorizing
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000631
632 Color the offending position instead of printing it and pointing at it
633 with a caret.
634
635 """
Guido van Rossum33d26892007-08-05 15:29:28 +0000636 tkconsole = self.tkconsole
637 text = tkconsole.text
638 text.tag_remove("ERROR", "1.0", "end")
David Scherer7aced172000-08-15 01:13:23 +0000639 type, value, tb = sys.exc_info()
Guido van Rossum33d26892007-08-05 15:29:28 +0000640 msg = value.msg or "<no detail available>"
641 lineno = value.lineno or 1
642 offset = value.offset or 0
643 if offset == 0:
644 lineno += 1 #mark end of offending line
645 if lineno == 1:
646 pos = "iomark + %d chars" % (offset-1)
David Scherer7aced172000-08-15 01:13:23 +0000647 else:
Guido van Rossum33d26892007-08-05 15:29:28 +0000648 pos = "iomark linestart + %d lines + %d chars" % \
649 (lineno-1, offset-1)
650 tkconsole.colorize_syntax_error(text, pos)
651 tkconsole.resetoutput()
652 self.write("SyntaxError: %s\n" % msg)
653 tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000654
655 def showtraceback(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000656 "Extend base class method to reset output properly"
David Scherer7aced172000-08-15 01:13:23 +0000657 self.tkconsole.resetoutput()
658 self.checklinecache()
659 InteractiveInterpreter.showtraceback(self)
Chui Tey5d2af632002-05-26 13:36:41 +0000660 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
661 self.tkconsole.open_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +0000662
663 def checklinecache(self):
664 c = linecache.cache
Guido van Rossum36e0a922007-07-20 04:05:57 +0000665 for key in list(c.keys()):
David Scherer7aced172000-08-15 01:13:23 +0000666 if key[:1] + key[-1:] != "<>":
667 del c[key]
668
Chui Tey5d2af632002-05-26 13:36:41 +0000669 def runcommand(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000670 "Run the code without invoking the debugger"
Chui Tey5d2af632002-05-26 13:36:41 +0000671 # The code better not raise an exception!
672 if self.tkconsole.executing:
Neal Norwitzf4c4f112002-11-30 18:49:10 +0000673 self.display_executing_dialog()
Chui Tey5d2af632002-05-26 13:36:41 +0000674 return 0
675 if self.rpcclt:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000676 self.rpcclt.remotequeue("exec", "runcode", (code,), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000677 else:
Georg Brandl7cae87c2006-09-06 06:51:57 +0000678 exec(code, self.locals)
Chui Tey5d2af632002-05-26 13:36:41 +0000679 return 1
680
David Scherer7aced172000-08-15 01:13:23 +0000681 def runcode(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000682 "Override base class method"
Chui Tey5d2af632002-05-26 13:36:41 +0000683 if self.tkconsole.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000684 self.interp.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000685 self.checklinecache()
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000686 if self.save_warnings_filters is not None:
687 warnings.filters[:] = self.save_warnings_filters
688 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000689 debugger = self.debugger
690 try:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000691 self.tkconsole.beginexecuting()
Thomas Wouterscf297e42007-02-23 15:07:44 +0000692 if not debugger and self.rpcclt is not None:
693 self.active_seq = self.rpcclt.asyncqueue("exec", "runcode",
694 (code,), {})
695 elif debugger:
696 debugger.run(code, self.locals)
697 else:
698 exec(code, self.locals)
699 except SystemExit:
700 if not self.tkconsole.closing:
701 if tkMessageBox.askyesno(
702 "Exit?",
703 "Do you want to exit altogether?",
704 default="yes",
705 master=self.tkconsole.text):
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000706 raise
Thomas Wouterscf297e42007-02-23 15:07:44 +0000707 else:
Guido van Rossum5dc0d972007-02-25 22:37:36 +0000708 self.showtraceback()
Thomas Wouterscf297e42007-02-23 15:07:44 +0000709 else:
710 raise
711 except:
712 if use_subprocess:
713 print("IDLE internal error in runcode()",
714 file=self.tkconsole.stderr)
David Scherer7aced172000-08-15 01:13:23 +0000715 self.showtraceback()
Thomas Wouterscf297e42007-02-23 15:07:44 +0000716 self.tkconsole.endexecuting()
717 else:
718 if self.tkconsole.canceled:
719 self.tkconsole.canceled = False
720 print("KeyboardInterrupt", file=self.tkconsole.stderr)
721 else:
722 self.showtraceback()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000723 finally:
724 if not use_subprocess:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000725 try:
726 self.tkconsole.endexecuting()
727 except AttributeError: # shell may have closed
728 pass
David Scherer7aced172000-08-15 01:13:23 +0000729
730 def write(self, s):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000731 "Override base class method"
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000732 self.tkconsole.stderr.write(s)
David Scherer7aced172000-08-15 01:13:23 +0000733
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000734 def display_port_binding_error(self):
735 tkMessageBox.showerror(
736 "Port Binding Error",
737 "IDLE can't bind TCP/IP port 8833, which is necessary to "
738 "communicate with its Python execution server. Either "
739 "no networking is installed on this computer or another "
740 "process (another IDLE?) is using the port. Run IDLE with the -n "
741 "command line switch to start without a subprocess and refer to "
742 "Help/IDLE Help 'Running without a subprocess' for further "
743 "details.",
744 master=self.tkconsole.text)
745
746 def display_no_subprocess_error(self):
747 tkMessageBox.showerror(
748 "Subprocess Startup Error",
749 "IDLE's subprocess didn't make connection. Either IDLE can't "
750 "start a subprocess or personal firewall software is blocking "
751 "the connection.",
752 master=self.tkconsole.text)
753
754 def display_executing_dialog(self):
755 tkMessageBox.showerror(
756 "Already executing",
757 "The Python Shell window is already executing a command; "
758 "please wait until it is finished.",
759 master=self.tkconsole.text)
760
761
David Scherer7aced172000-08-15 01:13:23 +0000762class PyShell(OutputWindow):
763
764 shell_title = "Python Shell"
765
766 # Override classes
767 ColorDelegator = ModifiedColorDelegator
768 UndoDelegator = ModifiedUndoDelegator
769
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000770 # Override menus
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000771 menu_specs = [
772 ("file", "_File"),
773 ("edit", "_Edit"),
Kurt B. Kaiser4cc5ef52003-01-22 00:23:23 +0000774 ("debug", "_Debug"),
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000775 ("options", "_Options"),
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000776 ("windows", "_Windows"),
777 ("help", "_Help"),
778 ]
David Scherer7aced172000-08-15 01:13:23 +0000779
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000780 if macosxSupport.runningAsOSXApp():
781 del menu_specs[-3]
782 menu_specs[-2] = ("windows", "_Window")
783
784
David Scherer7aced172000-08-15 01:13:23 +0000785 # New classes
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000786 from idlelib.IdleHistory import History
David Scherer7aced172000-08-15 01:13:23 +0000787
788 def __init__(self, flist=None):
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000789 if use_subprocess:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000790 ms = self.menu_specs
791 if ms[2][0] != "shell":
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000792 ms.insert(2, ("shell", "She_ll"))
David Scherer7aced172000-08-15 01:13:23 +0000793 self.interp = ModifiedInterpreter(self)
794 if flist is None:
795 root = Tk()
796 fixwordbreaks(root)
797 root.withdraw()
798 flist = PyShellFileList(root)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000799 #
David Scherer7aced172000-08-15 01:13:23 +0000800 OutputWindow.__init__(self, flist, None, None)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000801 #
Kurt B. Kaiser6af44982005-01-19 00:22:59 +0000802## self.config(usetabs=1, indentwidth=8, context_use_ps1=1)
803 self.usetabs = True
804 # indentwidth must be 8 when using tabs. See note in EditorWindow:
805 self.indentwidth = 8
806 self.context_use_ps1 = True
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000807 #
David Scherer7aced172000-08-15 01:13:23 +0000808 text = self.text
809 text.configure(wrap="char")
810 text.bind("<<newline-and-indent>>", self.enter_callback)
811 text.bind("<<plain-newline-and-indent>>", self.linefeed_callback)
812 text.bind("<<interrupt-execution>>", self.cancel_callback)
David Scherer7aced172000-08-15 01:13:23 +0000813 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. Kaiser8a78cad2007-12-13 03:38:16 +0000817 self.color = color = self.ColorDelegator()
818 self.per.insertfilter(color)
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000819 if use_subprocess:
820 text.bind("<<view-restart>>", self.view_restart_mark)
821 text.bind("<<restart-shell>>", self.restart_shell)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000822 #
David Scherer7aced172000-08-15 01:13:23 +0000823 self.save_stdout = sys.stdout
824 self.save_stderr = sys.stderr
825 self.save_stdin = sys.stdin
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000826 from idlelib import IOBinding
Martin v. Löwisbcc651a2003-06-22 07:52:56 +0000827 self.stdout = PseudoFile(self, "stdout", IOBinding.encoding)
828 self.stderr = PseudoFile(self, "stderr", IOBinding.encoding)
829 self.console = PseudoFile(self, "console", IOBinding.encoding)
Chui Tey5d2af632002-05-26 13:36:41 +0000830 if not use_subprocess:
831 sys.stdout = self.stdout
Kurt B. Kaiser7cec2522007-08-31 04:15:13 +0000832 sys.stderr = self.stderr
Chui Tey5d2af632002-05-26 13:36:41 +0000833 sys.stdin = self
Kurt B. Kaiserf609a342007-12-28 03:57:56 +0000834 try:
835 # page help() text to shell.
836 import pydoc # import must be done here to capture i/o rebinding.
837 # XXX KBK 27Dec07 use a textView someday, but must work w/o subproc
838 pydoc.pager = pydoc.plainpager
839 except:
840 sys.stderr = sys.__stderr__
841 raise
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000842 #
David Scherer7aced172000-08-15 01:13:23 +0000843 self.history = self.History(self.text)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000844 #
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000845 self.pollinterval = 50 # millisec
Chui Tey5d2af632002-05-26 13:36:41 +0000846
Kurt B. Kaiser4d5bc602004-06-06 01:29:22 +0000847 def get_standard_extension_names(self):
848 return idleConf.GetExtensions(shell_only=True)
849
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000850 reading = False
851 executing = False
852 canceled = False
853 endoffile = False
854 closing = False
David Scherer7aced172000-08-15 01:13:23 +0000855
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +0000856 def set_warning_stream(self, stream):
Skip Montanarod9161422004-07-06 21:53:27 +0000857 global warning_stream
858 warning_stream = stream
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +0000859
860 def get_warning_stream(self):
861 return warning_stream
862
David Scherer7aced172000-08-15 01:13:23 +0000863 def toggle_debugger(self, event=None):
864 if self.executing:
865 tkMessageBox.showerror("Don't debug now",
866 "You can only toggle the debugger when idle",
867 master=self.text)
868 self.set_debugger_indicator()
869 return "break"
870 else:
871 db = self.interp.getdebugger()
872 if db:
873 self.close_debugger()
874 else:
875 self.open_debugger()
876
877 def set_debugger_indicator(self):
878 db = self.interp.getdebugger()
879 self.setvar("<<toggle-debugger>>", not not db)
880
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000881 def toggle_jit_stack_viewer(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +0000882 pass # All we need is the variable
883
884 def close_debugger(self):
885 db = self.interp.getdebugger()
886 if db:
887 self.interp.setdebugger(None)
888 db.close()
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000889 if self.interp.rpcclt:
890 RemoteDebugger.close_remote_debugger(self.interp.rpcclt)
David Scherer7aced172000-08-15 01:13:23 +0000891 self.resetoutput()
892 self.console.write("[DEBUG OFF]\n")
893 sys.ps1 = ">>> "
894 self.showprompt()
895 self.set_debugger_indicator()
896
897 def open_debugger(self):
Chui Tey5d2af632002-05-26 13:36:41 +0000898 if self.interp.rpcclt:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000899 dbg_gui = RemoteDebugger.start_remote_debugger(self.interp.rpcclt,
900 self)
901 else:
902 dbg_gui = Debugger.Debugger(self)
903 self.interp.setdebugger(dbg_gui)
904 dbg_gui.load_breakpoints()
Chui Tey5d2af632002-05-26 13:36:41 +0000905 sys.ps1 = "[DEBUG ON]\n>>> "
906 self.showprompt()
907 self.set_debugger_indicator()
908
David Scherer7aced172000-08-15 01:13:23 +0000909 def beginexecuting(self):
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000910 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +0000911 self.resetoutput()
912 self.executing = 1
David Scherer7aced172000-08-15 01:13:23 +0000913
914 def endexecuting(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000915 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +0000916 self.executing = 0
917 self.canceled = 0
Chui Tey5d2af632002-05-26 13:36:41 +0000918 self.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000919
920 def close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000921 "Extend EditorWindow.close()"
David Scherer7aced172000-08-15 01:13:23 +0000922 if self.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000923 response = tkMessageBox.askokcancel(
David Scherer7aced172000-08-15 01:13:23 +0000924 "Kill?",
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000925 "The program is still running!\n Do you want to kill it?",
David Scherer7aced172000-08-15 01:13:23 +0000926 default="ok",
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000927 parent=self.text)
Benjamin Peterson2a691a82008-03-31 01:51:45 +0000928 if response is False:
David Scherer7aced172000-08-15 01:13:23 +0000929 return "cancel"
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +0000930 if self.reading:
931 self.top.quit()
932 self.canceled = True
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000933 self.closing = True
934 # Wait for poll_subprocess() rescheduling to stop
935 self.text.after(2 * self.pollinterval, self.close2)
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000936
937 def close2(self):
938 return EditorWindow.close(self)
David Scherer7aced172000-08-15 01:13:23 +0000939
940 def _close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000941 "Extend EditorWindow._close(), shut down debugger and execution server"
David Scherer7aced172000-08-15 01:13:23 +0000942 self.close_debugger()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000943 if use_subprocess:
944 self.interp.kill_subprocess()
David Scherer7aced172000-08-15 01:13:23 +0000945 # Restore std streams
946 sys.stdout = self.save_stdout
947 sys.stderr = self.save_stderr
948 sys.stdin = self.save_stdin
949 # Break cycles
950 self.interp = None
951 self.console = None
David Scherer7aced172000-08-15 01:13:23 +0000952 self.flist.pyshell = None
953 self.history = None
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000954 EditorWindow._close(self)
David Scherer7aced172000-08-15 01:13:23 +0000955
956 def ispythonsource(self, filename):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000957 "Override EditorWindow method: never remove the colorizer"
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000958 return True
David Scherer7aced172000-08-15 01:13:23 +0000959
960 def short_title(self):
961 return self.shell_title
962
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000963 COPYRIGHT = \
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000964 'Type "copyright", "credits" or "license()" for more information.'
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000965
Kurt B. Kaiser220fecf2003-07-27 03:24:19 +0000966 firewallmessage = """
967 ****************************************************************
968 Personal firewall software may warn about the connection IDLE
969 makes to its subprocess using this computer's internal loopback
970 interface. This connection is not visible on any external
971 interface and no data is sent to or received from the Internet.
972 ****************************************************************
973 """
974
David Scherer7aced172000-08-15 01:13:23 +0000975 def begin(self):
Kurt B. Kaiser7378df72007-08-11 04:20:51 +0000976 self.text.mark_set("iomark", "insert")
David Scherer7aced172000-08-15 01:13:23 +0000977 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000978 if use_subprocess:
979 nosub = ''
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000980 client = self.interp.start_subprocess()
981 if not client:
982 self.close()
Kurt B. Kaiser76637292004-01-21 22:10:01 +0000983 return False
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000984 else:
985 nosub = "==== No Subprocess ===="
Kurt B. Kaiser220fecf2003-07-27 03:24:19 +0000986 self.write("Python %s on %s\n%s\n%s\nIDLE %s %s\n" %
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000987 (sys.version, sys.platform, self.COPYRIGHT,
Kurt B. Kaiser220fecf2003-07-27 03:24:19 +0000988 self.firewallmessage, idlever.IDLE_VERSION, nosub))
David Scherer7aced172000-08-15 01:13:23 +0000989 self.showprompt()
Georg Brandl14fc4272008-05-17 18:39:55 +0000990 import tkinter
991 tkinter._default_root = None # 03Jan04 KBK What's this?
Kurt B. Kaiser76637292004-01-21 22:10:01 +0000992 return True
David Scherer7aced172000-08-15 01:13:23 +0000993
994 def readline(self):
995 save = self.reading
996 try:
997 self.reading = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +0000998 self.top.mainloop() # nested mainloop()
David Scherer7aced172000-08-15 01:13:23 +0000999 finally:
1000 self.reading = save
1001 line = self.text.get("iomark", "end-1c")
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001002 if len(line) == 0: # may be EOF if we quit our mainloop with Ctrl-C
1003 line = "\n"
David Scherer7aced172000-08-15 01:13:23 +00001004 self.resetoutput()
1005 if self.canceled:
1006 self.canceled = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001007 if not use_subprocess:
1008 raise KeyboardInterrupt
David Scherer7aced172000-08-15 01:13:23 +00001009 if self.endoffile:
1010 self.endoffile = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001011 line = ""
David Scherer7aced172000-08-15 01:13:23 +00001012 return line
1013
1014 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001015 return True
David Scherer7aced172000-08-15 01:13:23 +00001016
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001017 def cancel_callback(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +00001018 try:
1019 if self.text.compare("sel.first", "!=", "sel.last"):
1020 return # Active selection -- always use default binding
1021 except:
1022 pass
1023 if not (self.executing or self.reading):
1024 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001025 self.interp.write("KeyboardInterrupt\n")
David Scherer7aced172000-08-15 01:13:23 +00001026 self.showprompt()
1027 return "break"
1028 self.endoffile = 0
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001029 self.canceled = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001030 if (self.executing and self.interp.rpcclt):
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +00001031 if self.interp.getdebugger():
1032 self.interp.restart_subprocess()
1033 else:
1034 self.interp.interrupt_subprocess()
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001035 if self.reading:
1036 self.top.quit() # exit the nested mainloop() in readline()
David Scherer7aced172000-08-15 01:13:23 +00001037 return "break"
1038
1039 def eof_callback(self, event):
1040 if self.executing and not self.reading:
1041 return # Let the default binding (delete next char) take over
1042 if not (self.text.compare("iomark", "==", "insert") and
1043 self.text.compare("insert", "==", "end-1c")):
1044 return # Let the default binding (delete next char) take over
1045 if not self.executing:
David Scherer7aced172000-08-15 01:13:23 +00001046 self.resetoutput()
1047 self.close()
1048 else:
1049 self.canceled = 0
1050 self.endoffile = 1
1051 self.top.quit()
1052 return "break"
1053
David Scherer7aced172000-08-15 01:13:23 +00001054 def linefeed_callback(self, event):
1055 # Insert a linefeed without entering anything (still autoindented)
1056 if self.reading:
1057 self.text.insert("insert", "\n")
1058 self.text.see("insert")
1059 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001060 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001061 return "break"
1062
1063 def enter_callback(self, event):
1064 if self.executing and not self.reading:
1065 return # Let the default binding (insert '\n') take over
1066 # If some text is selected, recall the selection
1067 # (but only if this before the I/O mark)
1068 try:
1069 sel = self.text.get("sel.first", "sel.last")
1070 if sel:
1071 if self.text.compare("sel.last", "<=", "iomark"):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001072 self.recall(sel, event)
David Scherer7aced172000-08-15 01:13:23 +00001073 return "break"
1074 except:
1075 pass
1076 # If we're strictly before the line containing iomark, recall
1077 # the current line, less a leading prompt, less leading or
1078 # trailing whitespace
1079 if self.text.compare("insert", "<", "iomark linestart"):
1080 # Check if there's a relevant stdin range -- if so, use it
1081 prev = self.text.tag_prevrange("stdin", "insert")
1082 if prev and self.text.compare("insert", "<", prev[1]):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001083 self.recall(self.text.get(prev[0], prev[1]), event)
David Scherer7aced172000-08-15 01:13:23 +00001084 return "break"
1085 next = self.text.tag_nextrange("stdin", "insert")
1086 if next and self.text.compare("insert lineend", ">=", next[0]):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001087 self.recall(self.text.get(next[0], next[1]), event)
David Scherer7aced172000-08-15 01:13:23 +00001088 return "break"
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001089 # No stdin mark -- just get the current line, less any prompt
Kurt B. Kaiserb1754452005-11-18 22:05:48 +00001090 indices = self.text.tag_nextrange("console", "insert linestart")
1091 if indices and \
1092 self.text.compare(indices[0], "<=", "insert linestart"):
1093 self.recall(self.text.get(indices[1], "insert lineend"), event)
1094 else:
1095 self.recall(self.text.get("insert linestart", "insert lineend"), event)
David Scherer7aced172000-08-15 01:13:23 +00001096 return "break"
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001097 # If we're between the beginning of the line and the iomark, i.e.
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001098 # in the prompt area, move to the end of the prompt
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001099 if self.text.compare("insert", "<", "iomark"):
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001100 self.text.mark_set("insert", "iomark")
David Scherer7aced172000-08-15 01:13:23 +00001101 # If we're in the current input and there's only whitespace
1102 # beyond the cursor, erase that whitespace first
1103 s = self.text.get("insert", "end-1c")
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001104 if s and not s.strip():
David Scherer7aced172000-08-15 01:13:23 +00001105 self.text.delete("insert", "end-1c")
1106 # If we're in the current input before its last line,
1107 # insert a newline right at the insert point
1108 if self.text.compare("insert", "<", "end-1c linestart"):
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001109 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001110 return "break"
1111 # We're in the last line; append a newline and submit it
1112 self.text.mark_set("insert", "end-1c")
1113 if self.reading:
1114 self.text.insert("insert", "\n")
1115 self.text.see("insert")
1116 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001117 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001118 self.text.tag_add("stdin", "iomark", "end-1c")
1119 self.text.update_idletasks()
1120 if self.reading:
Neal Norwitzce96f692006-03-17 06:49:51 +00001121 self.top.quit() # Break out of recursive mainloop()
David Scherer7aced172000-08-15 01:13:23 +00001122 else:
1123 self.runit()
1124 return "break"
1125
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001126 def recall(self, s, event):
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001127 # remove leading and trailing empty or whitespace lines
1128 s = re.sub(r'^\s*\n', '' , s)
1129 s = re.sub(r'\n\s*$', '', s)
1130 lines = s.split('\n')
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001131 self.text.undo_block_start()
1132 try:
1133 self.text.tag_remove("sel", "1.0", "end")
1134 self.text.mark_set("insert", "end-1c")
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001135 prefix = self.text.get("insert linestart", "insert")
1136 if prefix.rstrip().endswith(':'):
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001137 self.newline_and_indent_event(event)
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001138 prefix = self.text.get("insert linestart", "insert")
1139 self.text.insert("insert", lines[0].strip())
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001140 if len(lines) > 1:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001141 orig_base_indent = re.search(r'^([ \t]*)', lines[0]).group(0)
1142 new_base_indent = re.search(r'^([ \t]*)', prefix).group(0)
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001143 for line in lines[1:]:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001144 if line.startswith(orig_base_indent):
1145 # replace orig base indentation with new indentation
1146 line = new_base_indent + line[len(orig_base_indent):]
1147 self.text.insert('insert', '\n'+line.rstrip())
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001148 finally:
1149 self.text.see("insert")
1150 self.text.undo_block_stop()
David Scherer7aced172000-08-15 01:13:23 +00001151
1152 def runit(self):
1153 line = self.text.get("iomark", "end-1c")
1154 # Strip off last newline and surrounding whitespace.
1155 # (To allow you to hit return twice to end a statement.)
1156 i = len(line)
1157 while i > 0 and line[i-1] in " \t":
1158 i = i-1
1159 if i > 0 and line[i-1] == "\n":
1160 i = i-1
1161 while i > 0 and line[i-1] in " \t":
1162 i = i-1
1163 line = line[:i]
1164 more = self.interp.runsource(line)
David Scherer7aced172000-08-15 01:13:23 +00001165
David Scherer7aced172000-08-15 01:13:23 +00001166 def open_stack_viewer(self, event=None):
Chui Tey5d2af632002-05-26 13:36:41 +00001167 if self.interp.rpcclt:
1168 return self.interp.remote_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +00001169 try:
1170 sys.last_traceback
1171 except:
1172 tkMessageBox.showerror("No stack trace",
1173 "There is no stack trace yet.\n"
1174 "(sys.last_traceback is not defined)",
1175 master=self.text)
1176 return
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +00001177 from idlelib.StackViewer import StackBrowser
David Scherer7aced172000-08-15 01:13:23 +00001178 sv = StackBrowser(self.root, self.flist)
1179
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001180 def view_restart_mark(self, event=None):
1181 self.text.see("iomark")
1182 self.text.see("restart")
1183
1184 def restart_shell(self, event=None):
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +00001185 self.interp.restart_subprocess()
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001186
David Scherer7aced172000-08-15 01:13:23 +00001187 def showprompt(self):
1188 self.resetoutput()
1189 try:
1190 s = str(sys.ps1)
1191 except:
1192 s = ""
1193 self.console.write(s)
1194 self.text.mark_set("insert", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001195 self.set_line_and_column()
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +00001196 self.io.reset_undo()
David Scherer7aced172000-08-15 01:13:23 +00001197
1198 def resetoutput(self):
1199 source = self.text.get("iomark", "end-1c")
1200 if self.history:
1201 self.history.history_store(source)
1202 if self.text.get("end-2c") != "\n":
1203 self.text.insert("end-1c", "\n")
1204 self.text.mark_set("iomark", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001205 self.set_line_and_column()
David Scherer7aced172000-08-15 01:13:23 +00001206
1207 def write(self, s, tags=()):
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001208 try:
1209 self.text.mark_gravity("iomark", "right")
1210 OutputWindow.write(self, s, tags, "iomark")
1211 self.text.mark_gravity("iomark", "left")
1212 except:
Kurt B. Kaisercbbe98f2007-08-12 01:52:35 +00001213 raise ###pass # ### 11Aug07 KBK if we are expecting exceptions
1214 # let's find out what they are and be specific.
David Scherer7aced172000-08-15 01:13:23 +00001215 if self.canceled:
1216 self.canceled = 0
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001217 if not use_subprocess:
1218 raise KeyboardInterrupt
David Scherer7aced172000-08-15 01:13:23 +00001219
Kurt B. Kaiserdcba6622004-12-21 22:10:32 +00001220class PseudoFile(object):
David Scherer7aced172000-08-15 01:13:23 +00001221
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001222 def __init__(self, shell, tags, encoding=None):
David Scherer7aced172000-08-15 01:13:23 +00001223 self.shell = shell
1224 self.tags = tags
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001225 self.encoding = encoding
David Scherer7aced172000-08-15 01:13:23 +00001226
1227 def write(self, s):
1228 self.shell.write(s, self.tags)
1229
Kurt B. Kaiser66aaf742007-08-09 18:00:23 +00001230 def writelines(self, lines):
1231 for line in lines:
1232 self.write(line)
David Scherer7aced172000-08-15 01:13:23 +00001233
1234 def flush(self):
1235 pass
1236
1237 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001238 return True
David Scherer7aced172000-08-15 01:13:23 +00001239
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001240
David Scherer7aced172000-08-15 01:13:23 +00001241usage_msg = """\
David Scherer7aced172000-08-15 01:13:23 +00001242
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001243USAGE: idle [-deins] [-t title] [file]*
1244 idle [-dns] [-t title] (-c cmd | -r file) [arg]*
1245 idle [-dns] [-t title] - [arg]*
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001246
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001247 -h print this help message and exit
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001248 -n run IDLE without a subprocess (see Help/IDLE Help for details)
David Scherer7aced172000-08-15 01:13:23 +00001249
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001250The following options will override the IDLE 'settings' configuration:
Kurt B. Kaiser96d88422001-07-17 04:59:01 +00001251
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001252 -e open an edit window
1253 -i open a shell window
1254
1255The following options imply -i and will open a shell:
1256
1257 -c cmd run the command in a shell, or
1258 -r file run script from file
1259
1260 -d enable the debugger
1261 -s run $IDLESTARTUP or $PYTHONSTARTUP before anything else
1262 -t title set title of shell window
1263
1264A default edit window will be bypassed when -c, -r, or - are used.
1265
1266[arg]* are passed to the command (-c) or script (-r) in sys.argv[1:].
1267
1268Examples:
1269
1270idle
1271 Open an edit window or shell depending on IDLE's configuration.
1272
1273idle foo.py foobar.py
1274 Edit the files, also open a shell if configured to start with shell.
1275
1276idle -est "Baz" foo.py
1277 Run $IDLESTARTUP or $PYTHONSTARTUP, edit foo.py, and open a shell
1278 window with the title "Baz".
1279
Neal Norwitz752abd02008-05-13 04:55:24 +00001280idle -c "import sys; print(sys.argv)" "foo"
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001281 Open a shell window and run the command, passing "-c" in sys.argv[0]
1282 and "foo" in sys.argv[1].
1283
1284idle -d -s -r foo.py "Hello World"
1285 Open a shell window, run a startup script, enable the debugger, and
1286 run foo.py, passing "foo.py" in sys.argv[0] and "Hello World" in
1287 sys.argv[1].
1288
Neal Norwitz752abd02008-05-13 04:55:24 +00001289echo "import sys; print(sys.argv)" | idle - "foobar"
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001290 Open a shell window, run the script piped in, passing '' in sys.argv[0]
1291 and "foobar" in sys.argv[1].
David Scherer7aced172000-08-15 01:13:23 +00001292"""
1293
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001294def main():
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001295 global flist, root, use_subprocess
David Scherer7aced172000-08-15 01:13:23 +00001296
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001297 use_subprocess = True
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001298 enable_shell = False
1299 enable_edit = False
1300 debug = False
1301 cmd = None
1302 script = None
1303 startup = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001304 try:
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001305 opts, args = getopt.getopt(sys.argv[1:], "c:deihnr:st:")
Guido van Rossumb940e112007-01-10 16:19:56 +00001306 except getopt.error as msg:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001307 sys.stderr.write("Error: %s\n" % str(msg))
1308 sys.stderr.write(usage_msg)
1309 sys.exit(2)
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001310 for o, a in opts:
1311 if o == '-c':
1312 cmd = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001313 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001314 if o == '-d':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001315 debug = True
1316 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001317 if o == '-e':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001318 enable_edit = True
1319 if o == '-h':
1320 sys.stdout.write(usage_msg)
1321 sys.exit()
1322 if o == '-i':
1323 enable_shell = True
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001324 if o == '-n':
1325 use_subprocess = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001326 if o == '-r':
1327 script = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001328 if os.path.isfile(script):
1329 pass
1330 else:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001331 print("No script file: ", script)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001332 sys.exit()
1333 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001334 if o == '-s':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001335 startup = True
1336 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001337 if o == '-t':
1338 PyShell.shell_title = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001339 enable_shell = True
1340 if args and args[0] == '-':
1341 cmd = sys.stdin.read()
1342 enable_shell = True
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001343 # process sys.argv and sys.path:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001344 for i in range(len(sys.path)):
1345 sys.path[i] = os.path.abspath(sys.path[i])
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001346 if args and args[0] == '-':
1347 sys.argv = [''] + args[1:]
1348 elif cmd:
1349 sys.argv = ['-c'] + args
1350 elif script:
1351 sys.argv = [script] + args
1352 elif args:
1353 enable_edit = True
1354 pathx = []
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001355 for filename in args:
1356 pathx.append(os.path.dirname(filename))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001357 for dir in pathx:
1358 dir = os.path.abspath(dir)
1359 if not dir in sys.path:
1360 sys.path.insert(0, dir)
Kurt B. Kaiserff002b92002-12-21 21:39:11 +00001361 else:
Neal Norwitzd082b6e2007-08-26 23:37:53 +00001362 dir = os.getcwd()
1363 if dir not in sys.path:
Kurt B. Kaiserff002b92002-12-21 21:39:11 +00001364 sys.path.insert(0, dir)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001365 # check the IDLE settings configuration (but command line overrides)
1366 edit_start = idleConf.GetOption('main', 'General',
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001367 'editor-on-startup', type='bool')
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001368 enable_edit = enable_edit or edit_start
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001369 enable_shell = enable_shell or not edit_start
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001370 # start editor and/or shell windows:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001371 root = Tk(className="Idle")
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001372
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001373 fixwordbreaks(root)
1374 root.withdraw()
1375 flist = PyShellFileList(root)
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001376 macosxSupport.setupApp(root, flist)
1377
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001378 if enable_edit:
1379 if not (cmd or script):
1380 for filename in args:
1381 flist.open(filename)
1382 if not args:
1383 flist.new()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001384 if enable_shell:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001385 shell = flist.open_shell()
1386 if not shell:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001387 return # couldn't open shell
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001388
1389 if macosxSupport.runningAsOSXApp() and flist.dict:
1390 # On OSX: when the user has double-clicked on a file that causes
1391 # IDLE to be launched the shell window will open just in front of
1392 # the file she wants to see. Lower the interpreter window when
1393 # there are open files.
1394 shell.top.lower()
1395
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001396 shell = flist.pyshell
1397 # handle remaining options:
1398 if debug:
1399 shell.open_debugger()
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001400 if startup:
1401 filename = os.environ.get("IDLESTARTUP") or \
1402 os.environ.get("PYTHONSTARTUP")
1403 if filename and os.path.isfile(filename):
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001404 shell.interp.execfile(filename)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001405 if shell and cmd or script:
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001406 shell.interp.runcommand("""if 1:
1407 import sys as _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001408 _sys.argv = %r
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001409 del _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001410 \n""" % (sys.argv,))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001411 if cmd:
1412 shell.interp.execsource(cmd)
1413 elif script:
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001414 shell.interp.prepend_syspath(script)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001415 shell.interp.execfile(script)
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001416
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001417 root.mainloop()
1418 root.destroy()
1419
David Scherer7aced172000-08-15 01:13:23 +00001420if __name__ == "__main__":
Kurt B. Kaiser9e8b8282003-06-15 17:38:45 +00001421 sys.modules['PyShell'] = sys.modules['__main__']
David Scherer7aced172000-08-15 01:13:23 +00001422 main()