blob: 43e08f2c78d4598783b27097bea8ce543eaa1ef6 [file] [log] [blame]
Benjamin Peterson90f5ba52010-03-11 22:53:45 +00001#! /usr/bin/env python3
David Scherer7aced172000-08-15 01:13:23 +00002
Victor Stinner979482a2011-09-02 01:00:40 +02003import getopt
David Scherer7aced172000-08-15 01:13:23 +00004import os
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +00005import os.path
David Scherer7aced172000-08-15 01:13:23 +00006import re
Chui Tey5d2af632002-05-26 13:36:41 +00007import socket
Victor Stinner979482a2011-09-02 01:00:40 +02008import subprocess
9import sys
Kurt B. Kaiser003091c2003-02-17 18:57:16 +000010import threading
Victor Stinner979482a2011-09-02 01:00:40 +020011import time
12import tokenize
Chui Tey5d2af632002-05-26 13:36:41 +000013import traceback
Kurt B. Kaiser62833982002-09-18 17:07:05 +000014import types
David Scherer7aced172000-08-15 01:13:23 +000015
16import linecache
17from code import InteractiveInterpreter
18
Kurt B. Kaiser2303b1c2003-11-24 05:26:16 +000019try:
Georg Brandl14fc4272008-05-17 18:39:55 +000020 from tkinter import *
Kurt B. Kaiser2303b1c2003-11-24 05:26:16 +000021except ImportError:
Guido van Rossumbe19ed72007-02-09 05:37:30 +000022 print("** IDLE can't import Tkinter. " \
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +000023 "Your Python may not be configured for Tk. **", file=sys.__stderr__)
Kurt B. Kaiser2303b1c2003-11-24 05:26:16 +000024 sys.exit(1)
Georg Brandl14fc4272008-05-17 18:39:55 +000025import tkinter.messagebox as tkMessageBox
David Scherer7aced172000-08-15 01:13:23 +000026
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +000027from idlelib.EditorWindow import EditorWindow, fixwordbreaks
28from idlelib.FileList import FileList
29from idlelib.ColorDelegator import ColorDelegator
30from idlelib.UndoDelegator import UndoDelegator
31from idlelib.OutputWindow import OutputWindow
32from idlelib.configHandler import idleConf
33from idlelib import idlever
34from idlelib import rpc
35from idlelib import Debugger
36from idlelib import RemoteDebugger
37from idlelib import macosxSupport
Chui Tey5d2af632002-05-26 13:36:41 +000038
Kurt B. Kaisere866c812009-04-04 21:07:39 +000039HOST = '127.0.0.1' # python execution server on localhost loopback
40PORT = 0 # someday pass in host, port for remote debug capability
Kurt B. Kaiserb9764192002-09-23 04:10:37 +000041
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000042# Override warnings module to write to warning_stream. Initialize to send IDLE
43# internal warnings to the console. ScriptBinding.check_syntax() will
44# temporarily redirect the stream to the shell window to display warnings when
45# checking user's code.
46global warning_stream
47warning_stream = sys.__stderr__
Chui Tey5d2af632002-05-26 13:36:41 +000048try:
49 import warnings
50except ImportError:
51 pass
52else:
Benjamin Peterson206e3072008-10-19 14:07:49 +000053 def idle_showwarning(message, category, filename, lineno,
54 file=None, line=None):
Guilherme Polo1fff0082009-08-14 15:05:30 +000055 if file is None:
56 file = warning_stream
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000057 try:
Guilherme Polo1fff0082009-08-14 15:05:30 +000058 file.write(warnings.formatwarning(message, category, filename,
Senthil Kumaranaa90e7c2011-07-03 17:39:20 -070059 lineno, line=line))
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000060 except IOError:
61 pass ## file (probably __stderr__) is invalid, warning dropped.
Chui Tey5d2af632002-05-26 13:36:41 +000062 warnings.showwarning = idle_showwarning
Guilherme Polo1fff0082009-08-14 15:05:30 +000063 def idle_formatwarning(message, category, filename, lineno, line=None):
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000064 """Format warnings the IDLE way"""
65 s = "\nWarning (from warnings module):\n"
66 s += ' File \"%s\", line %s\n' % (filename, lineno)
Guilherme Polo1fff0082009-08-14 15:05:30 +000067 if line is None:
68 line = linecache.getline(filename, lineno)
69 line = line.strip()
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000070 if line:
71 s += " %s\n" % line
72 s += "%s: %s\n>>> " % (category.__name__, message)
73 return s
74 warnings.formatwarning = idle_formatwarning
Chui Tey5d2af632002-05-26 13:36:41 +000075
Kurt B. Kaiserf7a88992004-11-13 21:05:58 +000076def extended_linecache_checkcache(filename=None,
77 orig_checkcache=linecache.checkcache):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +000078 """Extend linecache.checkcache to preserve the <pyshell#...> entries
79
Kurt B. Kaiserf7a88992004-11-13 21:05:58 +000080 Rather than repeating the linecache code, patch it to save the
81 <pyshell#...> entries, call the original linecache.checkcache()
Guilherme Polo1fff0082009-08-14 15:05:30 +000082 (skipping them), and then restore the saved entries.
Kurt B. Kaiserf7a88992004-11-13 21:05:58 +000083
84 orig_checkcache is bound at definition time to the original
85 method, allowing it to be patched.
Kurt B. Kaiser45186c42002-10-23 04:48:08 +000086 """
David Scherer7aced172000-08-15 01:13:23 +000087 cache = linecache.cache
88 save = {}
Guilherme Polo1fff0082009-08-14 15:05:30 +000089 for key in list(cache):
90 if key[:1] + key[-1:] == '<>':
91 save[key] = cache.pop(key)
92 orig_checkcache(filename)
David Scherer7aced172000-08-15 01:13:23 +000093 cache.update(save)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +000094
Kurt B. Kaiser81885592002-11-29 22:10:53 +000095# Patch linecache.checkcache():
96linecache.checkcache = extended_linecache_checkcache
David Scherer7aced172000-08-15 01:13:23 +000097
Kurt B. Kaiser45186c42002-10-23 04:48:08 +000098
David Scherer7aced172000-08-15 01:13:23 +000099class PyShellEditorWindow(EditorWindow):
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000100 "Regular text edit window in IDLE, supports breakpoints"
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000101
David Scherer7aced172000-08-15 01:13:23 +0000102 def __init__(self, *args):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000103 self.breakpoints = []
Raymond Hettinger931237e2003-07-09 18:48:24 +0000104 EditorWindow.__init__(self, *args)
David Scherer7aced172000-08-15 01:13:23 +0000105 self.text.bind("<<set-breakpoint-here>>", self.set_breakpoint_here)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000106 self.text.bind("<<clear-breakpoint-here>>", self.clear_breakpoint_here)
David Scherer7aced172000-08-15 01:13:23 +0000107 self.text.bind("<<open-python-shell>>", self.flist.open_shell)
108
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000109 self.breakpointPath = os.path.join(idleConf.GetUserCfgDir(),
110 'breakpoints.lst')
Chui Teya2adb0f2002-11-04 22:14:54 +0000111 # whenever a file is changed, restore breakpoints
112 if self.io.filename: self.restore_file_breaks()
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000113 def filename_changed_hook(old_hook=self.io.filename_change_hook,
114 self=self):
Chui Teya2adb0f2002-11-04 22:14:54 +0000115 self.restore_file_breaks()
116 old_hook()
117 self.io.set_filename_change_hook(filename_changed_hook)
118
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000119 rmenu_specs = [("Set Breakpoint", "<<set-breakpoint-here>>"),
120 ("Clear Breakpoint", "<<clear-breakpoint-here>>")]
David Scherer7aced172000-08-15 01:13:23 +0000121
Chui Teya2adb0f2002-11-04 22:14:54 +0000122 def set_breakpoint(self, lineno):
123 text = self.text
124 filename = self.io.filename
125 text.tag_add("BREAK", "%d.0" % lineno, "%d.0" % (lineno+1))
126 try:
127 i = self.breakpoints.index(lineno)
128 except ValueError: # only add if missing, i.e. do once
129 self.breakpoints.append(lineno)
130 try: # update the subprocess debugger
131 debug = self.flist.pyshell.interp.debugger
132 debug.set_breakpoint_here(filename, lineno)
133 except: # but debugger may not be active right now....
134 pass
135
David Scherer7aced172000-08-15 01:13:23 +0000136 def set_breakpoint_here(self, event=None):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000137 text = self.text
138 filename = self.io.filename
139 if not filename:
140 text.bell()
David Scherer7aced172000-08-15 01:13:23 +0000141 return
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000142 lineno = int(float(text.index("insert")))
Chui Teya2adb0f2002-11-04 22:14:54 +0000143 self.set_breakpoint(lineno)
David Scherer7aced172000-08-15 01:13:23 +0000144
Kurt B. Kaiser669f4c32002-06-20 04:01:47 +0000145 def clear_breakpoint_here(self, event=None):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000146 text = self.text
147 filename = self.io.filename
148 if not filename:
149 text.bell()
Kurt B. Kaiser669f4c32002-06-20 04:01:47 +0000150 return
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000151 lineno = int(float(text.index("insert")))
152 try:
153 self.breakpoints.remove(lineno)
154 except:
155 pass
156 text.tag_remove("BREAK", "insert linestart",\
157 "insert lineend +1char")
158 try:
159 debug = self.flist.pyshell.interp.debugger
160 debug.clear_breakpoint_here(filename, lineno)
161 except:
162 pass
163
164 def clear_file_breaks(self):
165 if self.breakpoints:
166 text = self.text
167 filename = self.io.filename
168 if not filename:
169 text.bell()
170 return
171 self.breakpoints = []
172 text.tag_remove("BREAK", "1.0", END)
173 try:
174 debug = self.flist.pyshell.interp.debugger
175 debug.clear_file_breaks(filename)
176 except:
177 pass
178
Chui Teya2adb0f2002-11-04 22:14:54 +0000179 def store_file_breaks(self):
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000180 "Save breakpoints when file is saved"
181 # XXX 13 Dec 2002 KBK Currently the file must be saved before it can
182 # be run. The breaks are saved at that time. If we introduce
183 # a temporary file save feature the save breaks functionality
184 # needs to be re-verified, since the breaks at the time the
185 # temp file is created may differ from the breaks at the last
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000186 # permanent save of the file. Currently, a break introduced
187 # after a save will be effective, but not persistent.
188 # This is necessary to keep the saved breaks synched with the
189 # saved file.
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000190 #
191 # Breakpoints are set as tagged ranges in the text. Certain
192 # kinds of edits cause these ranges to be deleted: Inserting
193 # or deleting a line just before a breakpoint, and certain
194 # deletions prior to a breakpoint. These issues need to be
195 # investigated and understood. It's not clear if they are
196 # Tk issues or IDLE issues, or whether they can actually
197 # be fixed. Since a modified file has to be saved before it is
198 # run, and since self.breakpoints (from which the subprocess
199 # debugger is loaded) is updated during the save, the visible
200 # breaks stay synched with the subprocess even if one of these
201 # unexpected breakpoint deletions occurs.
202 breaks = self.breakpoints
203 filename = self.io.filename
Chui Teya2adb0f2002-11-04 22:14:54 +0000204 try:
Victor Stinner85c67722011-09-02 00:57:04 +0200205 with open(self.breakpointPath, "r") as fp:
206 lines = fp.readlines()
Chui Teya2adb0f2002-11-04 22:14:54 +0000207 except IOError:
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000208 lines = []
Victor Stinner85c67722011-09-02 00:57:04 +0200209 with open(self.breakpointPath, "w") as new_file:
210 for line in lines:
211 if not line.startswith(filename + '='):
212 new_file.write(line)
213 self.update_breakpoints()
214 breaks = self.breakpoints
215 if breaks:
216 new_file.write(filename + '=' + str(breaks) + '\n')
Chui Teya2adb0f2002-11-04 22:14:54 +0000217
218 def restore_file_breaks(self):
219 self.text.update() # this enables setting "BREAK" tags to be visible
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000220 filename = self.io.filename
221 if filename is None:
222 return
Chui Tey69371d62002-11-04 23:39:45 +0000223 if os.path.isfile(self.breakpointPath):
Victor Stinner85c67722011-09-02 00:57:04 +0200224 with open(self.breakpointPath, "r") as fp:
225 lines = fp.readlines()
Chui Tey69371d62002-11-04 23:39:45 +0000226 for line in lines:
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000227 if line.startswith(filename + '='):
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000228 breakpoint_linenumbers = eval(line[len(filename)+1:])
Chui Tey69371d62002-11-04 23:39:45 +0000229 for breakpoint_linenumber in breakpoint_linenumbers:
230 self.set_breakpoint(breakpoint_linenumber)
Chui Teya2adb0f2002-11-04 22:14:54 +0000231
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000232 def update_breakpoints(self):
233 "Retrieves all the breakpoints in the current window"
Chui Teya2adb0f2002-11-04 22:14:54 +0000234 text = self.text
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000235 ranges = text.tag_ranges("BREAK")
236 linenumber_list = self.ranges_to_linenumbers(ranges)
237 self.breakpoints = linenumber_list
238
239 def ranges_to_linenumbers(self, ranges):
240 lines = []
241 for index in range(0, len(ranges), 2):
242 lineno = int(float(ranges[index]))
243 end = int(float(ranges[index+1]))
244 while lineno < end:
245 lines.append(lineno)
246 lineno += 1
247 return lines
248
Kurt B. Kaiser11220fa2002-12-24 00:57:22 +0000249# XXX 13 Dec 2002 KBK Not used currently
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000250# def saved_change_hook(self):
251# "Extend base method - clear breaks if module is modified"
252# if not self.get_saved():
253# self.clear_file_breaks()
254# EditorWindow.saved_change_hook(self)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000255
256 def _close(self):
257 "Extend base method - clear breaks when module is closed"
258 self.clear_file_breaks()
259 EditorWindow._close(self)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000260
David Scherer7aced172000-08-15 01:13:23 +0000261
262class PyShellFileList(FileList):
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000263 "Extend base class: IDLE supports a shell and breakpoints"
David Scherer7aced172000-08-15 01:13:23 +0000264
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000265 # override FileList's class variable, instances return PyShellEditorWindow
266 # instead of EditorWindow when new edit windows are created.
David Scherer7aced172000-08-15 01:13:23 +0000267 EditorWindow = PyShellEditorWindow
268
269 pyshell = None
270
271 def open_shell(self, event=None):
272 if self.pyshell:
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000273 self.pyshell.top.wakeup()
David Scherer7aced172000-08-15 01:13:23 +0000274 else:
275 self.pyshell = PyShell(self)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000276 if self.pyshell:
277 if not self.pyshell.begin():
278 return None
David Scherer7aced172000-08-15 01:13:23 +0000279 return self.pyshell
280
281
282class ModifiedColorDelegator(ColorDelegator):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000283 "Extend base class: colorizer for the shell window itself"
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000284
Steven M. Gavab77d3432002-03-02 07:16:21 +0000285 def __init__(self):
286 ColorDelegator.__init__(self)
287 self.LoadTagDefs()
David Scherer7aced172000-08-15 01:13:23 +0000288
289 def recolorize_main(self):
290 self.tag_remove("TODO", "1.0", "iomark")
291 self.tag_add("SYNC", "1.0", "iomark")
292 ColorDelegator.recolorize_main(self)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000293
Steven M. Gavab77d3432002-03-02 07:16:21 +0000294 def LoadTagDefs(self):
295 ColorDelegator.LoadTagDefs(self)
296 theme = idleConf.GetOption('main','Theme','name')
297 self.tagdefs.update({
298 "stdin": {'background':None,'foreground':None},
299 "stdout": idleConf.GetHighlight(theme, "stdout"),
300 "stderr": idleConf.GetHighlight(theme, "stderr"),
301 "console": idleConf.GetHighlight(theme, "console"),
Steven M. Gavab77d3432002-03-02 07:16:21 +0000302 })
David Scherer7aced172000-08-15 01:13:23 +0000303
David Scherer7aced172000-08-15 01:13:23 +0000304class ModifiedUndoDelegator(UndoDelegator):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000305 "Extend base class: forbid insert/delete before the I/O mark"
David Scherer7aced172000-08-15 01:13:23 +0000306
307 def insert(self, index, chars, tags=None):
308 try:
309 if self.delegate.compare(index, "<", "iomark"):
310 self.delegate.bell()
311 return
312 except TclError:
313 pass
314 UndoDelegator.insert(self, index, chars, tags)
315
316 def delete(self, index1, index2=None):
317 try:
318 if self.delegate.compare(index1, "<", "iomark"):
319 self.delegate.bell()
320 return
321 except TclError:
322 pass
323 UndoDelegator.delete(self, index1, index2)
324
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000325
326class MyRPCClient(rpc.RPCClient):
327
328 def handle_EOF(self):
329 "Override the base class - just re-raise EOFError"
330 raise EOFError
331
Kurt B. Kaiser8d1f11b2003-05-26 22:20:34 +0000332
David Scherer7aced172000-08-15 01:13:23 +0000333class ModifiedInterpreter(InteractiveInterpreter):
334
335 def __init__(self, tkconsole):
336 self.tkconsole = tkconsole
337 locals = sys.modules['__main__'].__dict__
338 InteractiveInterpreter.__init__(self, locals=locals)
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000339 self.save_warnings_filters = None
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000340 self.restarting = False
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000341 self.subprocess_arglist = None
342 self.port = PORT
David Scherer7aced172000-08-15 01:13:23 +0000343
Chui Tey5d2af632002-05-26 13:36:41 +0000344 rpcclt = None
Ned Deilye5cad232011-08-02 18:47:13 -0700345 rpcsubproc = None
Chui Tey5d2af632002-05-26 13:36:41 +0000346
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000347 def spawn_subprocess(self):
Florent Xiclunafd1b0932010-03-28 00:25:02 +0000348 if self.subprocess_arglist is None:
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000349 self.subprocess_arglist = self.build_subprocess_arglist()
Ned Deilye5cad232011-08-02 18:47:13 -0700350 self.rpcsubproc = subprocess.Popen(self.subprocess_arglist)
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000351
Tony Lowndsf53dec22002-12-20 04:24:43 +0000352 def build_subprocess_arglist(self):
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000353 assert (self.port!=0), (
354 "Socket should have been assigned a port number.")
Tony Lownds2398d572003-05-13 15:28:21 +0000355 w = ['-W' + s for s in sys.warnoptions]
356 # Maybe IDLE is installed and is being accessed via sys.path,
357 # or maybe it's not installed and the idle.py script is being
358 # run from the IDLE source directory.
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000359 del_exitf = idleConf.GetOption('main', 'General', 'delete-exitfunc',
360 default=False, type='bool')
Tony Lownds2398d572003-05-13 15:28:21 +0000361 if __name__ == 'idlelib.PyShell':
Walter Dörwald70a6b492004-02-12 17:35:32 +0000362 command = "__import__('idlelib.run').run.main(%r)" % (del_exitf,)
Tony Lowndsf2324b92002-09-29 00:34:10 +0000363 else:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000364 command = "__import__('run').main(%r)" % (del_exitf,)
Ned Deilye5cad232011-08-02 18:47:13 -0700365 return [sys.executable] + w + ["-c", command, str(self.port)]
Tony Lowndsf2324b92002-09-29 00:34:10 +0000366
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000367 def start_subprocess(self):
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000368 addr = (HOST, self.port)
369 # GUI makes several attempts to acquire socket, listens for connection
Kurt B. Kaiser5db48432003-05-15 03:40:51 +0000370 for i in range(3):
Chui Tey5d2af632002-05-26 13:36:41 +0000371 time.sleep(i)
372 try:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000373 self.rpcclt = MyRPCClient(addr)
Chui Tey5d2af632002-05-26 13:36:41 +0000374 break
Guido van Rossumb940e112007-01-10 16:19:56 +0000375 except socket.error as err:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000376 pass
Chui Tey5d2af632002-05-26 13:36:41 +0000377 else:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000378 self.display_port_binding_error()
379 return None
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000380 # if PORT was 0, system will assign an 'ephemeral' port. Find it out:
381 self.port = self.rpcclt.listening_sock.getsockname()[1]
382 # if PORT was not 0, probably working with a remote execution server
383 if PORT != 0:
384 # To allow reconnection within the 2MSL wait (cf. Stevens TCP
385 # V1, 18.6), set SO_REUSEADDR. Note that this can be problematic
386 # on Windows since the implementation allows two active sockets on
387 # the same address!
388 self.rpcclt.listening_sock.setsockopt(socket.SOL_SOCKET,
389 socket.SO_REUSEADDR, 1)
390 self.spawn_subprocess()
391 #time.sleep(20) # test to simulate GUI not accepting connection
Kurt B. Kaiserb4179362002-07-26 00:06:42 +0000392 # Accept the connection from the Python execution server
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000393 self.rpcclt.listening_sock.settimeout(10)
394 try:
395 self.rpcclt.accept()
Guido van Rossumb940e112007-01-10 16:19:56 +0000396 except socket.timeout as err:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000397 self.display_no_subprocess_error()
398 return None
Kurt B. Kaiser969de452002-06-12 03:28:57 +0000399 self.rpcclt.register("stdin", self.tkconsole)
400 self.rpcclt.register("stdout", self.tkconsole.stdout)
401 self.rpcclt.register("stderr", self.tkconsole.stderr)
Chui Tey5d2af632002-05-26 13:36:41 +0000402 self.rpcclt.register("flist", self.tkconsole.flist)
Kurt B. Kaiser8cd0def2003-01-31 05:06:43 +0000403 self.rpcclt.register("linecache", linecache)
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000404 self.rpcclt.register("interp", self)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000405 self.transfer_path()
Chui Tey5d2af632002-05-26 13:36:41 +0000406 self.poll_subprocess()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000407 return self.rpcclt
Chui Tey5d2af632002-05-26 13:36:41 +0000408
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000409 def restart_subprocess(self):
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000410 if self.restarting:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000411 return self.rpcclt
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000412 self.restarting = True
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000413 # close only the subprocess debugger
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000414 debug = self.getdebugger()
415 if debug:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000416 try:
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000417 # Only close subprocess debugger, don't unregister gui_adap!
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000418 RemoteDebugger.close_subprocess_debugger(self.rpcclt)
419 except:
420 pass
421 # Kill subprocess, spawn a new one, accept connection.
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000422 self.rpcclt.close()
Ned Deilye5cad232011-08-02 18:47:13 -0700423 self.terminate_subprocess()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000424 console = self.tkconsole
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000425 was_executing = console.executing
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000426 console.executing = False
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000427 self.spawn_subprocess()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000428 try:
429 self.rpcclt.accept()
Guido van Rossumb940e112007-01-10 16:19:56 +0000430 except socket.timeout as err:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000431 self.display_no_subprocess_error()
432 return None
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000433 self.transfer_path()
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000434 # annotate restart in shell window and mark it
Kurt B. Kaiser4cc5ef52003-01-22 00:23:23 +0000435 console.text.delete("iomark", "end-1c")
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000436 if was_executing:
437 console.write('\n')
438 console.showprompt()
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000439 halfbar = ((int(console.width) - 16) // 2) * '='
440 console.write(halfbar + ' RESTART ' + halfbar)
441 console.text.mark_set("restart", "end-1c")
442 console.text.mark_gravity("restart", "left")
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000443 console.showprompt()
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000444 # restart subprocess debugger
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000445 if debug:
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000446 # Restarted debugger connects to current instance of debug GUI
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000447 gui = RemoteDebugger.restart_subprocess_debugger(self.rpcclt)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000448 # reload remote debugger breakpoints for all PyShellEditWindows
449 debug.load_breakpoints()
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000450 self.restarting = False
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000451 return self.rpcclt
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000452
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000453 def __request_interrupt(self):
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000454 self.rpcclt.remotecall("exec", "interrupt_the_server", (), {})
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000455
456 def interrupt_subprocess(self):
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000457 threading.Thread(target=self.__request_interrupt).start()
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000458
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000459 def kill_subprocess(self):
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000460 try:
461 self.rpcclt.close()
462 except AttributeError: # no socket
463 pass
Ned Deilye5cad232011-08-02 18:47:13 -0700464 self.terminate_subprocess()
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000465 self.tkconsole.executing = False
466 self.rpcclt = None
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000467
Ned Deilye5cad232011-08-02 18:47:13 -0700468 def terminate_subprocess(self):
469 "Make sure subprocess is terminated"
470 try:
471 self.rpcsubproc.kill()
472 except OSError:
473 # process already terminated
474 return
475 else:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000476 try:
Ned Deilye5cad232011-08-02 18:47:13 -0700477 self.rpcsubproc.wait()
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000478 except OSError:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000479 return
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000480
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000481 def transfer_path(self):
482 self.runcommand("""if 1:
483 import sys as _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +0000484 _sys.path = %r
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000485 del _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +0000486 \n""" % (sys.path,))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000487
Chui Tey5d2af632002-05-26 13:36:41 +0000488 active_seq = None
489
490 def poll_subprocess(self):
491 clt = self.rpcclt
492 if clt is None:
493 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000494 try:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000495 response = clt.pollresponse(self.active_seq, wait=0.05)
496 except (EOFError, IOError, KeyboardInterrupt):
497 # lost connection or subprocess terminated itself, restart
498 # [the KBI is from rpc.SocketIO.handle_EOF()]
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000499 if self.tkconsole.closing:
500 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000501 response = None
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000502 self.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000503 if response:
504 self.tkconsole.resetoutput()
505 self.active_seq = None
506 how, what = response
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000507 console = self.tkconsole.console
Chui Tey5d2af632002-05-26 13:36:41 +0000508 if how == "OK":
509 if what is not None:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000510 print(repr(what), file=console)
Chui Tey5d2af632002-05-26 13:36:41 +0000511 elif how == "EXCEPTION":
Chui Tey5d2af632002-05-26 13:36:41 +0000512 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
513 self.remote_stack_viewer()
514 elif how == "ERROR":
Kurt B. Kaiser0930c432002-12-06 21:45:24 +0000515 errmsg = "PyShell.ModifiedInterpreter: Subprocess ERROR:\n"
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000516 print(errmsg, what, file=sys.__stderr__)
517 print(errmsg, what, file=console)
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000518 # we received a response to the currently active seq number:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000519 try:
520 self.tkconsole.endexecuting()
521 except AttributeError: # shell may have closed
522 pass
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000523 # Reschedule myself
524 if not self.tkconsole.closing:
525 self.tkconsole.text.after(self.tkconsole.pollinterval,
526 self.poll_subprocess)
Chui Tey5d2af632002-05-26 13:36:41 +0000527
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000528 debugger = None
529
530 def setdebugger(self, debugger):
531 self.debugger = debugger
532
533 def getdebugger(self):
534 return self.debugger
535
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000536 def open_remote_stack_viewer(self):
537 """Initiate the remote stack viewer from a separate thread.
538
539 This method is called from the subprocess, and by returning from this
540 method we allow the subprocess to unblock. After a bit the shell
541 requests the subprocess to open the remote stack viewer which returns a
Ezio Melotti60861182010-07-23 16:48:22 +0000542 static object looking at the last exception. It is queried through
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000543 the RPC mechanism.
544
545 """
546 self.tkconsole.text.after(300, self.remote_stack_viewer)
547 return
548
Chui Tey5d2af632002-05-26 13:36:41 +0000549 def remote_stack_viewer(self):
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000550 from idlelib import RemoteObjectBrowser
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000551 oid = self.rpcclt.remotequeue("exec", "stackviewer", ("flist",), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000552 if oid is None:
553 self.tkconsole.root.bell()
554 return
555 item = RemoteObjectBrowser.StubObjectTreeItem(self.rpcclt, oid)
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000556 from idlelib.TreeWidget import ScrolledCanvas, TreeNode
Chui Tey5d2af632002-05-26 13:36:41 +0000557 top = Toplevel(self.tkconsole.root)
Kurt B. Kaiser73360a32004-03-08 18:15:31 +0000558 theme = idleConf.GetOption('main','Theme','name')
559 background = idleConf.GetHighlight(theme, 'normal')['background']
560 sc = ScrolledCanvas(top, bg=background, highlightthickness=0)
Chui Tey5d2af632002-05-26 13:36:41 +0000561 sc.frame.pack(expand=1, fill="both")
562 node = TreeNode(sc.canvas, None, item)
563 node.expand()
564 # XXX Should GC the remote tree when closing the window
565
David Scherer7aced172000-08-15 01:13:23 +0000566 gid = 0
567
568 def execsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000569 "Like runsource() but assumes complete exec source"
David Scherer7aced172000-08-15 01:13:23 +0000570 filename = self.stuffsource(source)
571 self.execfile(filename, source)
572
573 def execfile(self, filename, source=None):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000574 "Execute an existing file"
David Scherer7aced172000-08-15 01:13:23 +0000575 if source is None:
Victor Stinner979482a2011-09-02 01:00:40 +0200576 with tokenize.open(filename) as fp:
Victor Stinner85c67722011-09-02 00:57:04 +0200577 source = fp.read()
David Scherer7aced172000-08-15 01:13:23 +0000578 try:
579 code = compile(source, filename, "exec")
580 except (OverflowError, SyntaxError):
581 self.tkconsole.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000582 tkerr = self.tkconsole.stderr
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000583 print('*** Error in script or command!\n', file=tkerr)
584 print('Traceback (most recent call last):', file=tkerr)
David Scherer7aced172000-08-15 01:13:23 +0000585 InteractiveInterpreter.showsyntaxerror(self, filename)
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000586 self.tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000587 else:
588 self.runcode(code)
589
590 def runsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000591 "Extend base class method: Stuff the source in the line cache first"
David Scherer7aced172000-08-15 01:13:23 +0000592 filename = self.stuffsource(source)
593 self.more = 0
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000594 self.save_warnings_filters = warnings.filters[:]
595 warnings.filterwarnings(action="error", category=SyntaxWarning)
Martin v. Löwis98ff8982007-08-13 06:03:15 +0000596 # at the moment, InteractiveInterpreter expects str
597 assert isinstance(source, str)
598 #if isinstance(source, str):
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000599 # from idlelib import IOBinding
Martin v. Löwis98ff8982007-08-13 06:03:15 +0000600 # try:
601 # source = source.encode(IOBinding.encoding)
602 # except UnicodeError:
603 # self.tkconsole.resetoutput()
604 # self.write("Unsupported characters in input\n")
605 # return
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000606 try:
Kurt B. Kaiser935ea9a2005-05-10 03:44:24 +0000607 # InteractiveInterpreter.runsource() calls its runcode() method,
608 # which is overridden (see below)
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000609 return InteractiveInterpreter.runsource(self, source, filename)
610 finally:
611 if self.save_warnings_filters is not None:
612 warnings.filters[:] = self.save_warnings_filters
613 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000614
615 def stuffsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000616 "Stuff source in the filename cache"
David Scherer7aced172000-08-15 01:13:23 +0000617 filename = "<pyshell#%d>" % self.gid
618 self.gid = self.gid + 1
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000619 lines = source.split("\n")
David Scherer7aced172000-08-15 01:13:23 +0000620 linecache.cache[filename] = len(source)+1, 0, lines, filename
621 return filename
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000622
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000623 def prepend_syspath(self, filename):
624 "Prepend sys.path with file's directory if not already included"
625 self.runcommand("""if 1:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000626 _filename = %r
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000627 import sys as _sys
628 from os.path import dirname as _dirname
629 _dir = _dirname(_filename)
630 if not _dir in _sys.path:
631 _sys.path.insert(0, _dir)
632 del _filename, _sys, _dirname, _dir
Walter Dörwald70a6b492004-02-12 17:35:32 +0000633 \n""" % (filename,))
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000634
David Scherer7aced172000-08-15 01:13:23 +0000635 def showsyntaxerror(self, filename=None):
Guido van Rossum33d26892007-08-05 15:29:28 +0000636 """Override Interactive Interpreter method: Use Colorizing
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000637
638 Color the offending position instead of printing it and pointing at it
639 with a caret.
640
641 """
Guido van Rossum33d26892007-08-05 15:29:28 +0000642 tkconsole = self.tkconsole
643 text = tkconsole.text
644 text.tag_remove("ERROR", "1.0", "end")
David Scherer7aced172000-08-15 01:13:23 +0000645 type, value, tb = sys.exc_info()
Ned Deily79746422011-09-14 14:49:14 -0700646 msg = getattr(value, 'msg', '') or value or "<no detail available>"
647 lineno = getattr(value, 'lineno', '') or 1
648 offset = getattr(value, 'offset', '') or 0
Guido van Rossum33d26892007-08-05 15:29:28 +0000649 if offset == 0:
650 lineno += 1 #mark end of offending line
651 if lineno == 1:
652 pos = "iomark + %d chars" % (offset-1)
David Scherer7aced172000-08-15 01:13:23 +0000653 else:
Guido van Rossum33d26892007-08-05 15:29:28 +0000654 pos = "iomark linestart + %d lines + %d chars" % \
655 (lineno-1, offset-1)
656 tkconsole.colorize_syntax_error(text, pos)
657 tkconsole.resetoutput()
658 self.write("SyntaxError: %s\n" % msg)
659 tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000660
661 def showtraceback(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000662 "Extend base class method to reset output properly"
David Scherer7aced172000-08-15 01:13:23 +0000663 self.tkconsole.resetoutput()
664 self.checklinecache()
665 InteractiveInterpreter.showtraceback(self)
Chui Tey5d2af632002-05-26 13:36:41 +0000666 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
667 self.tkconsole.open_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +0000668
669 def checklinecache(self):
670 c = linecache.cache
Guido van Rossum36e0a922007-07-20 04:05:57 +0000671 for key in list(c.keys()):
David Scherer7aced172000-08-15 01:13:23 +0000672 if key[:1] + key[-1:] != "<>":
673 del c[key]
674
Chui Tey5d2af632002-05-26 13:36:41 +0000675 def runcommand(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000676 "Run the code without invoking the debugger"
Chui Tey5d2af632002-05-26 13:36:41 +0000677 # The code better not raise an exception!
678 if self.tkconsole.executing:
Neal Norwitzf4c4f112002-11-30 18:49:10 +0000679 self.display_executing_dialog()
Chui Tey5d2af632002-05-26 13:36:41 +0000680 return 0
681 if self.rpcclt:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000682 self.rpcclt.remotequeue("exec", "runcode", (code,), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000683 else:
Georg Brandl7cae87c2006-09-06 06:51:57 +0000684 exec(code, self.locals)
Chui Tey5d2af632002-05-26 13:36:41 +0000685 return 1
686
David Scherer7aced172000-08-15 01:13:23 +0000687 def runcode(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000688 "Override base class method"
Chui Tey5d2af632002-05-26 13:36:41 +0000689 if self.tkconsole.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000690 self.interp.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000691 self.checklinecache()
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000692 if self.save_warnings_filters is not None:
693 warnings.filters[:] = self.save_warnings_filters
694 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000695 debugger = self.debugger
696 try:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000697 self.tkconsole.beginexecuting()
Thomas Wouterscf297e42007-02-23 15:07:44 +0000698 if not debugger and self.rpcclt is not None:
699 self.active_seq = self.rpcclt.asyncqueue("exec", "runcode",
700 (code,), {})
701 elif debugger:
702 debugger.run(code, self.locals)
703 else:
704 exec(code, self.locals)
705 except SystemExit:
706 if not self.tkconsole.closing:
707 if tkMessageBox.askyesno(
708 "Exit?",
709 "Do you want to exit altogether?",
710 default="yes",
711 master=self.tkconsole.text):
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000712 raise
Thomas Wouterscf297e42007-02-23 15:07:44 +0000713 else:
Guido van Rossum5dc0d972007-02-25 22:37:36 +0000714 self.showtraceback()
Thomas Wouterscf297e42007-02-23 15:07:44 +0000715 else:
716 raise
717 except:
718 if use_subprocess:
719 print("IDLE internal error in runcode()",
720 file=self.tkconsole.stderr)
David Scherer7aced172000-08-15 01:13:23 +0000721 self.showtraceback()
Thomas Wouterscf297e42007-02-23 15:07:44 +0000722 self.tkconsole.endexecuting()
723 else:
724 if self.tkconsole.canceled:
725 self.tkconsole.canceled = False
726 print("KeyboardInterrupt", file=self.tkconsole.stderr)
727 else:
728 self.showtraceback()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000729 finally:
730 if not use_subprocess:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000731 try:
732 self.tkconsole.endexecuting()
733 except AttributeError: # shell may have closed
734 pass
David Scherer7aced172000-08-15 01:13:23 +0000735
736 def write(self, s):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000737 "Override base class method"
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000738 self.tkconsole.stderr.write(s)
David Scherer7aced172000-08-15 01:13:23 +0000739
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000740 def display_port_binding_error(self):
741 tkMessageBox.showerror(
742 "Port Binding Error",
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000743 "IDLE can't bind to a TCP/IP port, which is necessary to "
744 "communicate with its Python execution server. This might be "
745 "because no networking is installed on this computer. "
746 "Run IDLE with the -n command line switch to start without a "
747 "subprocess and refer to Help/IDLE Help 'Running without a "
748 "subprocess' for further details.",
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000749 master=self.tkconsole.text)
750
751 def display_no_subprocess_error(self):
752 tkMessageBox.showerror(
753 "Subprocess Startup Error",
754 "IDLE's subprocess didn't make connection. Either IDLE can't "
755 "start a subprocess or personal firewall software is blocking "
756 "the connection.",
757 master=self.tkconsole.text)
758
759 def display_executing_dialog(self):
760 tkMessageBox.showerror(
761 "Already executing",
762 "The Python Shell window is already executing a command; "
763 "please wait until it is finished.",
764 master=self.tkconsole.text)
765
766
David Scherer7aced172000-08-15 01:13:23 +0000767class PyShell(OutputWindow):
768
769 shell_title = "Python Shell"
770
771 # Override classes
772 ColorDelegator = ModifiedColorDelegator
773 UndoDelegator = ModifiedUndoDelegator
774
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000775 # Override menus
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000776 menu_specs = [
777 ("file", "_File"),
778 ("edit", "_Edit"),
Kurt B. Kaiser4cc5ef52003-01-22 00:23:23 +0000779 ("debug", "_Debug"),
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000780 ("options", "_Options"),
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000781 ("windows", "_Windows"),
782 ("help", "_Help"),
783 ]
David Scherer7aced172000-08-15 01:13:23 +0000784
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000785 if macosxSupport.runningAsOSXApp():
786 del menu_specs[-3]
787 menu_specs[-2] = ("windows", "_Window")
788
789
David Scherer7aced172000-08-15 01:13:23 +0000790 # New classes
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000791 from idlelib.IdleHistory import History
David Scherer7aced172000-08-15 01:13:23 +0000792
793 def __init__(self, flist=None):
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000794 if use_subprocess:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000795 ms = self.menu_specs
796 if ms[2][0] != "shell":
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000797 ms.insert(2, ("shell", "She_ll"))
David Scherer7aced172000-08-15 01:13:23 +0000798 self.interp = ModifiedInterpreter(self)
799 if flist is None:
800 root = Tk()
801 fixwordbreaks(root)
802 root.withdraw()
803 flist = PyShellFileList(root)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000804 #
David Scherer7aced172000-08-15 01:13:23 +0000805 OutputWindow.__init__(self, flist, None, None)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000806 #
Kurt B. Kaiser6af44982005-01-19 00:22:59 +0000807## self.config(usetabs=1, indentwidth=8, context_use_ps1=1)
808 self.usetabs = True
809 # indentwidth must be 8 when using tabs. See note in EditorWindow:
810 self.indentwidth = 8
811 self.context_use_ps1 = True
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000812 #
David Scherer7aced172000-08-15 01:13:23 +0000813 text = self.text
814 text.configure(wrap="char")
815 text.bind("<<newline-and-indent>>", self.enter_callback)
816 text.bind("<<plain-newline-and-indent>>", self.linefeed_callback)
817 text.bind("<<interrupt-execution>>", self.cancel_callback)
David Scherer7aced172000-08-15 01:13:23 +0000818 text.bind("<<end-of-file>>", self.eof_callback)
819 text.bind("<<open-stack-viewer>>", self.open_stack_viewer)
Kurt B. Kaiser57bfe5d2003-05-10 00:09:52 +0000820 text.bind("<<toggle-debugger>>", self.toggle_debugger)
David Scherer7aced172000-08-15 01:13:23 +0000821 text.bind("<<toggle-jit-stack-viewer>>", self.toggle_jit_stack_viewer)
Kurt B. Kaiser8a78cad2007-12-13 03:38:16 +0000822 self.color = color = self.ColorDelegator()
823 self.per.insertfilter(color)
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000824 if use_subprocess:
825 text.bind("<<view-restart>>", self.view_restart_mark)
826 text.bind("<<restart-shell>>", self.restart_shell)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000827 #
David Scherer7aced172000-08-15 01:13:23 +0000828 self.save_stdout = sys.stdout
829 self.save_stderr = sys.stderr
830 self.save_stdin = sys.stdin
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000831 from idlelib import IOBinding
Martin v. Löwisbcc651a2003-06-22 07:52:56 +0000832 self.stdout = PseudoFile(self, "stdout", IOBinding.encoding)
833 self.stderr = PseudoFile(self, "stderr", IOBinding.encoding)
834 self.console = PseudoFile(self, "console", IOBinding.encoding)
Chui Tey5d2af632002-05-26 13:36:41 +0000835 if not use_subprocess:
836 sys.stdout = self.stdout
Kurt B. Kaiser7cec2522007-08-31 04:15:13 +0000837 sys.stderr = self.stderr
Chui Tey5d2af632002-05-26 13:36:41 +0000838 sys.stdin = self
Kurt B. Kaiserf609a342007-12-28 03:57:56 +0000839 try:
840 # page help() text to shell.
841 import pydoc # import must be done here to capture i/o rebinding.
842 # XXX KBK 27Dec07 use a textView someday, but must work w/o subproc
843 pydoc.pager = pydoc.plainpager
844 except:
845 sys.stderr = sys.__stderr__
846 raise
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000847 #
David Scherer7aced172000-08-15 01:13:23 +0000848 self.history = self.History(self.text)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000849 #
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000850 self.pollinterval = 50 # millisec
Chui Tey5d2af632002-05-26 13:36:41 +0000851
Kurt B. Kaiser4d5bc602004-06-06 01:29:22 +0000852 def get_standard_extension_names(self):
853 return idleConf.GetExtensions(shell_only=True)
854
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000855 reading = False
856 executing = False
857 canceled = False
858 endoffile = False
859 closing = False
David Scherer7aced172000-08-15 01:13:23 +0000860
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +0000861 def set_warning_stream(self, stream):
Skip Montanarod9161422004-07-06 21:53:27 +0000862 global warning_stream
863 warning_stream = stream
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +0000864
865 def get_warning_stream(self):
866 return warning_stream
867
David Scherer7aced172000-08-15 01:13:23 +0000868 def toggle_debugger(self, event=None):
869 if self.executing:
870 tkMessageBox.showerror("Don't debug now",
871 "You can only toggle the debugger when idle",
872 master=self.text)
873 self.set_debugger_indicator()
874 return "break"
875 else:
876 db = self.interp.getdebugger()
877 if db:
878 self.close_debugger()
879 else:
880 self.open_debugger()
881
882 def set_debugger_indicator(self):
883 db = self.interp.getdebugger()
884 self.setvar("<<toggle-debugger>>", not not db)
885
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000886 def toggle_jit_stack_viewer(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +0000887 pass # All we need is the variable
888
889 def close_debugger(self):
890 db = self.interp.getdebugger()
891 if db:
892 self.interp.setdebugger(None)
893 db.close()
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000894 if self.interp.rpcclt:
895 RemoteDebugger.close_remote_debugger(self.interp.rpcclt)
David Scherer7aced172000-08-15 01:13:23 +0000896 self.resetoutput()
897 self.console.write("[DEBUG OFF]\n")
898 sys.ps1 = ">>> "
899 self.showprompt()
900 self.set_debugger_indicator()
901
902 def open_debugger(self):
Chui Tey5d2af632002-05-26 13:36:41 +0000903 if self.interp.rpcclt:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000904 dbg_gui = RemoteDebugger.start_remote_debugger(self.interp.rpcclt,
905 self)
906 else:
907 dbg_gui = Debugger.Debugger(self)
908 self.interp.setdebugger(dbg_gui)
909 dbg_gui.load_breakpoints()
Chui Tey5d2af632002-05-26 13:36:41 +0000910 sys.ps1 = "[DEBUG ON]\n>>> "
911 self.showprompt()
912 self.set_debugger_indicator()
913
David Scherer7aced172000-08-15 01:13:23 +0000914 def beginexecuting(self):
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000915 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +0000916 self.resetoutput()
917 self.executing = 1
David Scherer7aced172000-08-15 01:13:23 +0000918
919 def endexecuting(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000920 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +0000921 self.executing = 0
922 self.canceled = 0
Chui Tey5d2af632002-05-26 13:36:41 +0000923 self.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000924
925 def close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000926 "Extend EditorWindow.close()"
David Scherer7aced172000-08-15 01:13:23 +0000927 if self.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000928 response = tkMessageBox.askokcancel(
David Scherer7aced172000-08-15 01:13:23 +0000929 "Kill?",
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000930 "The program is still running!\n Do you want to kill it?",
David Scherer7aced172000-08-15 01:13:23 +0000931 default="ok",
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000932 parent=self.text)
Benjamin Peterson2a691a82008-03-31 01:51:45 +0000933 if response is False:
David Scherer7aced172000-08-15 01:13:23 +0000934 return "cancel"
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +0000935 if self.reading:
936 self.top.quit()
937 self.canceled = True
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000938 self.closing = True
939 # Wait for poll_subprocess() rescheduling to stop
940 self.text.after(2 * self.pollinterval, self.close2)
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000941
942 def close2(self):
943 return EditorWindow.close(self)
David Scherer7aced172000-08-15 01:13:23 +0000944
945 def _close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000946 "Extend EditorWindow._close(), shut down debugger and execution server"
David Scherer7aced172000-08-15 01:13:23 +0000947 self.close_debugger()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000948 if use_subprocess:
949 self.interp.kill_subprocess()
David Scherer7aced172000-08-15 01:13:23 +0000950 # Restore std streams
951 sys.stdout = self.save_stdout
952 sys.stderr = self.save_stderr
953 sys.stdin = self.save_stdin
954 # Break cycles
955 self.interp = None
956 self.console = None
David Scherer7aced172000-08-15 01:13:23 +0000957 self.flist.pyshell = None
958 self.history = None
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000959 EditorWindow._close(self)
David Scherer7aced172000-08-15 01:13:23 +0000960
961 def ispythonsource(self, filename):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000962 "Override EditorWindow method: never remove the colorizer"
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000963 return True
David Scherer7aced172000-08-15 01:13:23 +0000964
965 def short_title(self):
966 return self.shell_title
967
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000968 COPYRIGHT = \
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000969 'Type "copyright", "credits" or "license()" for more information.'
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000970
David Scherer7aced172000-08-15 01:13:23 +0000971 def begin(self):
Kurt B. Kaiser7378df72007-08-11 04:20:51 +0000972 self.text.mark_set("iomark", "insert")
David Scherer7aced172000-08-15 01:13:23 +0000973 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000974 if use_subprocess:
975 nosub = ''
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000976 client = self.interp.start_subprocess()
977 if not client:
978 self.close()
Kurt B. Kaiser76637292004-01-21 22:10:01 +0000979 return False
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000980 else:
981 nosub = "==== No Subprocess ===="
Raymond Hettingera2a8e8b2009-01-27 00:28:36 +0000982 self.write("Python %s on %s\n%s\n%s" %
983 (sys.version, sys.platform, self.COPYRIGHT, nosub))
David Scherer7aced172000-08-15 01:13:23 +0000984 self.showprompt()
Georg Brandl14fc4272008-05-17 18:39:55 +0000985 import tkinter
986 tkinter._default_root = None # 03Jan04 KBK What's this?
Kurt B. Kaiser76637292004-01-21 22:10:01 +0000987 return True
David Scherer7aced172000-08-15 01:13:23 +0000988
989 def readline(self):
990 save = self.reading
991 try:
992 self.reading = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +0000993 self.top.mainloop() # nested mainloop()
David Scherer7aced172000-08-15 01:13:23 +0000994 finally:
995 self.reading = save
996 line = self.text.get("iomark", "end-1c")
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +0000997 if len(line) == 0: # may be EOF if we quit our mainloop with Ctrl-C
998 line = "\n"
David Scherer7aced172000-08-15 01:13:23 +0000999 self.resetoutput()
1000 if self.canceled:
1001 self.canceled = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001002 if not use_subprocess:
1003 raise KeyboardInterrupt
David Scherer7aced172000-08-15 01:13:23 +00001004 if self.endoffile:
1005 self.endoffile = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001006 line = ""
David Scherer7aced172000-08-15 01:13:23 +00001007 return line
1008
1009 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001010 return True
David Scherer7aced172000-08-15 01:13:23 +00001011
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001012 def cancel_callback(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +00001013 try:
1014 if self.text.compare("sel.first", "!=", "sel.last"):
1015 return # Active selection -- always use default binding
1016 except:
1017 pass
1018 if not (self.executing or self.reading):
1019 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001020 self.interp.write("KeyboardInterrupt\n")
David Scherer7aced172000-08-15 01:13:23 +00001021 self.showprompt()
1022 return "break"
1023 self.endoffile = 0
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001024 self.canceled = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001025 if (self.executing and self.interp.rpcclt):
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +00001026 if self.interp.getdebugger():
1027 self.interp.restart_subprocess()
1028 else:
1029 self.interp.interrupt_subprocess()
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001030 if self.reading:
1031 self.top.quit() # exit the nested mainloop() in readline()
David Scherer7aced172000-08-15 01:13:23 +00001032 return "break"
1033
1034 def eof_callback(self, event):
1035 if self.executing and not self.reading:
1036 return # Let the default binding (delete next char) take over
1037 if not (self.text.compare("iomark", "==", "insert") and
1038 self.text.compare("insert", "==", "end-1c")):
1039 return # Let the default binding (delete next char) take over
1040 if not self.executing:
David Scherer7aced172000-08-15 01:13:23 +00001041 self.resetoutput()
1042 self.close()
1043 else:
1044 self.canceled = 0
1045 self.endoffile = 1
1046 self.top.quit()
1047 return "break"
1048
David Scherer7aced172000-08-15 01:13:23 +00001049 def linefeed_callback(self, event):
1050 # Insert a linefeed without entering anything (still autoindented)
1051 if self.reading:
1052 self.text.insert("insert", "\n")
1053 self.text.see("insert")
1054 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001055 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001056 return "break"
1057
1058 def enter_callback(self, event):
1059 if self.executing and not self.reading:
1060 return # Let the default binding (insert '\n') take over
1061 # If some text is selected, recall the selection
1062 # (but only if this before the I/O mark)
1063 try:
1064 sel = self.text.get("sel.first", "sel.last")
1065 if sel:
1066 if self.text.compare("sel.last", "<=", "iomark"):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001067 self.recall(sel, event)
David Scherer7aced172000-08-15 01:13:23 +00001068 return "break"
1069 except:
1070 pass
1071 # If we're strictly before the line containing iomark, recall
1072 # the current line, less a leading prompt, less leading or
1073 # trailing whitespace
1074 if self.text.compare("insert", "<", "iomark linestart"):
1075 # Check if there's a relevant stdin range -- if so, use it
1076 prev = self.text.tag_prevrange("stdin", "insert")
1077 if prev and self.text.compare("insert", "<", prev[1]):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001078 self.recall(self.text.get(prev[0], prev[1]), event)
David Scherer7aced172000-08-15 01:13:23 +00001079 return "break"
1080 next = self.text.tag_nextrange("stdin", "insert")
1081 if next and self.text.compare("insert lineend", ">=", next[0]):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001082 self.recall(self.text.get(next[0], next[1]), event)
David Scherer7aced172000-08-15 01:13:23 +00001083 return "break"
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001084 # No stdin mark -- just get the current line, less any prompt
Kurt B. Kaiserb1754452005-11-18 22:05:48 +00001085 indices = self.text.tag_nextrange("console", "insert linestart")
1086 if indices and \
1087 self.text.compare(indices[0], "<=", "insert linestart"):
1088 self.recall(self.text.get(indices[1], "insert lineend"), event)
1089 else:
1090 self.recall(self.text.get("insert linestart", "insert lineend"), event)
David Scherer7aced172000-08-15 01:13:23 +00001091 return "break"
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001092 # If we're between the beginning of the line and the iomark, i.e.
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001093 # in the prompt area, move to the end of the prompt
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001094 if self.text.compare("insert", "<", "iomark"):
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001095 self.text.mark_set("insert", "iomark")
David Scherer7aced172000-08-15 01:13:23 +00001096 # If we're in the current input and there's only whitespace
1097 # beyond the cursor, erase that whitespace first
1098 s = self.text.get("insert", "end-1c")
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001099 if s and not s.strip():
David Scherer7aced172000-08-15 01:13:23 +00001100 self.text.delete("insert", "end-1c")
1101 # If we're in the current input before its last line,
1102 # insert a newline right at the insert point
1103 if self.text.compare("insert", "<", "end-1c linestart"):
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001104 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001105 return "break"
1106 # We're in the last line; append a newline and submit it
1107 self.text.mark_set("insert", "end-1c")
1108 if self.reading:
1109 self.text.insert("insert", "\n")
1110 self.text.see("insert")
1111 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001112 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001113 self.text.tag_add("stdin", "iomark", "end-1c")
1114 self.text.update_idletasks()
1115 if self.reading:
Neal Norwitzce96f692006-03-17 06:49:51 +00001116 self.top.quit() # Break out of recursive mainloop()
David Scherer7aced172000-08-15 01:13:23 +00001117 else:
1118 self.runit()
1119 return "break"
1120
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001121 def recall(self, s, event):
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001122 # remove leading and trailing empty or whitespace lines
1123 s = re.sub(r'^\s*\n', '' , s)
1124 s = re.sub(r'\n\s*$', '', s)
1125 lines = s.split('\n')
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001126 self.text.undo_block_start()
1127 try:
1128 self.text.tag_remove("sel", "1.0", "end")
1129 self.text.mark_set("insert", "end-1c")
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001130 prefix = self.text.get("insert linestart", "insert")
1131 if prefix.rstrip().endswith(':'):
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001132 self.newline_and_indent_event(event)
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001133 prefix = self.text.get("insert linestart", "insert")
1134 self.text.insert("insert", lines[0].strip())
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001135 if len(lines) > 1:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001136 orig_base_indent = re.search(r'^([ \t]*)', lines[0]).group(0)
1137 new_base_indent = re.search(r'^([ \t]*)', prefix).group(0)
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001138 for line in lines[1:]:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001139 if line.startswith(orig_base_indent):
1140 # replace orig base indentation with new indentation
1141 line = new_base_indent + line[len(orig_base_indent):]
1142 self.text.insert('insert', '\n'+line.rstrip())
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001143 finally:
1144 self.text.see("insert")
1145 self.text.undo_block_stop()
David Scherer7aced172000-08-15 01:13:23 +00001146
1147 def runit(self):
1148 line = self.text.get("iomark", "end-1c")
1149 # Strip off last newline and surrounding whitespace.
1150 # (To allow you to hit return twice to end a statement.)
1151 i = len(line)
1152 while i > 0 and line[i-1] in " \t":
1153 i = i-1
1154 if i > 0 and line[i-1] == "\n":
1155 i = i-1
1156 while i > 0 and line[i-1] in " \t":
1157 i = i-1
1158 line = line[:i]
1159 more = self.interp.runsource(line)
David Scherer7aced172000-08-15 01:13:23 +00001160
David Scherer7aced172000-08-15 01:13:23 +00001161 def open_stack_viewer(self, event=None):
Chui Tey5d2af632002-05-26 13:36:41 +00001162 if self.interp.rpcclt:
1163 return self.interp.remote_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +00001164 try:
1165 sys.last_traceback
1166 except:
1167 tkMessageBox.showerror("No stack trace",
1168 "There is no stack trace yet.\n"
1169 "(sys.last_traceback is not defined)",
1170 master=self.text)
1171 return
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +00001172 from idlelib.StackViewer import StackBrowser
David Scherer7aced172000-08-15 01:13:23 +00001173 sv = StackBrowser(self.root, self.flist)
1174
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001175 def view_restart_mark(self, event=None):
1176 self.text.see("iomark")
1177 self.text.see("restart")
1178
1179 def restart_shell(self, event=None):
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +00001180 self.interp.restart_subprocess()
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001181
David Scherer7aced172000-08-15 01:13:23 +00001182 def showprompt(self):
1183 self.resetoutput()
1184 try:
1185 s = str(sys.ps1)
1186 except:
1187 s = ""
1188 self.console.write(s)
1189 self.text.mark_set("insert", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001190 self.set_line_and_column()
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +00001191 self.io.reset_undo()
David Scherer7aced172000-08-15 01:13:23 +00001192
1193 def resetoutput(self):
1194 source = self.text.get("iomark", "end-1c")
1195 if self.history:
1196 self.history.history_store(source)
1197 if self.text.get("end-2c") != "\n":
1198 self.text.insert("end-1c", "\n")
1199 self.text.mark_set("iomark", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001200 self.set_line_and_column()
David Scherer7aced172000-08-15 01:13:23 +00001201
1202 def write(self, s, tags=()):
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001203 try:
1204 self.text.mark_gravity("iomark", "right")
1205 OutputWindow.write(self, s, tags, "iomark")
1206 self.text.mark_gravity("iomark", "left")
1207 except:
Kurt B. Kaisercbbe98f2007-08-12 01:52:35 +00001208 raise ###pass # ### 11Aug07 KBK if we are expecting exceptions
1209 # let's find out what they are and be specific.
David Scherer7aced172000-08-15 01:13:23 +00001210 if self.canceled:
1211 self.canceled = 0
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001212 if not use_subprocess:
1213 raise KeyboardInterrupt
David Scherer7aced172000-08-15 01:13:23 +00001214
Kurt B. Kaiserdcba6622004-12-21 22:10:32 +00001215class PseudoFile(object):
David Scherer7aced172000-08-15 01:13:23 +00001216
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001217 def __init__(self, shell, tags, encoding=None):
David Scherer7aced172000-08-15 01:13:23 +00001218 self.shell = shell
1219 self.tags = tags
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001220 self.encoding = encoding
David Scherer7aced172000-08-15 01:13:23 +00001221
1222 def write(self, s):
1223 self.shell.write(s, self.tags)
1224
Kurt B. Kaiser66aaf742007-08-09 18:00:23 +00001225 def writelines(self, lines):
1226 for line in lines:
1227 self.write(line)
David Scherer7aced172000-08-15 01:13:23 +00001228
1229 def flush(self):
1230 pass
1231
1232 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001233 return True
David Scherer7aced172000-08-15 01:13:23 +00001234
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001235
David Scherer7aced172000-08-15 01:13:23 +00001236usage_msg = """\
David Scherer7aced172000-08-15 01:13:23 +00001237
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001238USAGE: idle [-deins] [-t title] [file]*
1239 idle [-dns] [-t title] (-c cmd | -r file) [arg]*
1240 idle [-dns] [-t title] - [arg]*
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001241
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001242 -h print this help message and exit
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001243 -n run IDLE without a subprocess (see Help/IDLE Help for details)
David Scherer7aced172000-08-15 01:13:23 +00001244
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001245The following options will override the IDLE 'settings' configuration:
Kurt B. Kaiser96d88422001-07-17 04:59:01 +00001246
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001247 -e open an edit window
1248 -i open a shell window
1249
1250The following options imply -i and will open a shell:
1251
1252 -c cmd run the command in a shell, or
1253 -r file run script from file
1254
1255 -d enable the debugger
1256 -s run $IDLESTARTUP or $PYTHONSTARTUP before anything else
1257 -t title set title of shell window
1258
1259A default edit window will be bypassed when -c, -r, or - are used.
1260
1261[arg]* are passed to the command (-c) or script (-r) in sys.argv[1:].
1262
1263Examples:
1264
1265idle
1266 Open an edit window or shell depending on IDLE's configuration.
1267
1268idle foo.py foobar.py
1269 Edit the files, also open a shell if configured to start with shell.
1270
1271idle -est "Baz" foo.py
1272 Run $IDLESTARTUP or $PYTHONSTARTUP, edit foo.py, and open a shell
1273 window with the title "Baz".
1274
Neal Norwitz752abd02008-05-13 04:55:24 +00001275idle -c "import sys; print(sys.argv)" "foo"
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001276 Open a shell window and run the command, passing "-c" in sys.argv[0]
1277 and "foo" in sys.argv[1].
1278
1279idle -d -s -r foo.py "Hello World"
1280 Open a shell window, run a startup script, enable the debugger, and
1281 run foo.py, passing "foo.py" in sys.argv[0] and "Hello World" in
1282 sys.argv[1].
1283
Neal Norwitz752abd02008-05-13 04:55:24 +00001284echo "import sys; print(sys.argv)" | idle - "foobar"
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001285 Open a shell window, run the script piped in, passing '' in sys.argv[0]
1286 and "foobar" in sys.argv[1].
David Scherer7aced172000-08-15 01:13:23 +00001287"""
1288
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001289def main():
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001290 global flist, root, use_subprocess
David Scherer7aced172000-08-15 01:13:23 +00001291
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001292 use_subprocess = True
Kurt B. Kaisere866c812009-04-04 21:07:39 +00001293 enable_shell = True
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001294 enable_edit = False
1295 debug = False
1296 cmd = None
1297 script = None
1298 startup = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001299 try:
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001300 opts, args = getopt.getopt(sys.argv[1:], "c:deihnr:st:")
Guido van Rossumb940e112007-01-10 16:19:56 +00001301 except getopt.error as msg:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001302 sys.stderr.write("Error: %s\n" % str(msg))
1303 sys.stderr.write(usage_msg)
1304 sys.exit(2)
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001305 for o, a in opts:
1306 if o == '-c':
1307 cmd = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001308 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001309 if o == '-d':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001310 debug = True
1311 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001312 if o == '-e':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001313 enable_edit = True
Kurt B. Kaisere866c812009-04-04 21:07:39 +00001314 enable_shell = False
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001315 if o == '-h':
1316 sys.stdout.write(usage_msg)
1317 sys.exit()
1318 if o == '-i':
1319 enable_shell = True
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001320 if o == '-n':
1321 use_subprocess = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001322 if o == '-r':
1323 script = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001324 if os.path.isfile(script):
1325 pass
1326 else:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001327 print("No script file: ", script)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001328 sys.exit()
1329 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001330 if o == '-s':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001331 startup = True
1332 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001333 if o == '-t':
1334 PyShell.shell_title = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001335 enable_shell = True
1336 if args and args[0] == '-':
1337 cmd = sys.stdin.read()
1338 enable_shell = True
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001339 # process sys.argv and sys.path:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001340 for i in range(len(sys.path)):
1341 sys.path[i] = os.path.abspath(sys.path[i])
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001342 if args and args[0] == '-':
1343 sys.argv = [''] + args[1:]
1344 elif cmd:
1345 sys.argv = ['-c'] + args
1346 elif script:
1347 sys.argv = [script] + args
1348 elif args:
1349 enable_edit = True
1350 pathx = []
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001351 for filename in args:
1352 pathx.append(os.path.dirname(filename))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001353 for dir in pathx:
1354 dir = os.path.abspath(dir)
1355 if not dir in sys.path:
1356 sys.path.insert(0, dir)
Kurt B. Kaiserff002b92002-12-21 21:39:11 +00001357 else:
Neal Norwitzd082b6e2007-08-26 23:37:53 +00001358 dir = os.getcwd()
1359 if dir not in sys.path:
Kurt B. Kaiserff002b92002-12-21 21:39:11 +00001360 sys.path.insert(0, dir)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001361 # check the IDLE settings configuration (but command line overrides)
1362 edit_start = idleConf.GetOption('main', 'General',
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001363 'editor-on-startup', type='bool')
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001364 enable_edit = enable_edit or edit_start
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001365 # start editor and/or shell windows:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001366 root = Tk(className="Idle")
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001367
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001368 fixwordbreaks(root)
1369 root.withdraw()
1370 flist = PyShellFileList(root)
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001371 macosxSupport.setupApp(root, flist)
1372
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001373 if enable_edit:
1374 if not (cmd or script):
1375 for filename in args:
1376 flist.open(filename)
1377 if not args:
1378 flist.new()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001379 if enable_shell:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001380 shell = flist.open_shell()
1381 if not shell:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001382 return # couldn't open shell
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001383
1384 if macosxSupport.runningAsOSXApp() and flist.dict:
1385 # On OSX: when the user has double-clicked on a file that causes
1386 # IDLE to be launched the shell window will open just in front of
1387 # the file she wants to see. Lower the interpreter window when
1388 # there are open files.
1389 shell.top.lower()
1390
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001391 shell = flist.pyshell
1392 # handle remaining options:
1393 if debug:
1394 shell.open_debugger()
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001395 if startup:
1396 filename = os.environ.get("IDLESTARTUP") or \
1397 os.environ.get("PYTHONSTARTUP")
1398 if filename and os.path.isfile(filename):
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001399 shell.interp.execfile(filename)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001400 if shell and cmd or script:
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001401 shell.interp.runcommand("""if 1:
1402 import sys as _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001403 _sys.argv = %r
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001404 del _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001405 \n""" % (sys.argv,))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001406 if cmd:
1407 shell.interp.execsource(cmd)
1408 elif script:
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001409 shell.interp.prepend_syspath(script)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001410 shell.interp.execfile(script)
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001411
Ned Deily4ce92b22011-01-15 04:37:12 +00001412 # Check for problematic OS X Tk versions and print a warning message
1413 # in the IDLE shell window; this is less intrusive than always opening
1414 # a separate window.
1415 tkversionwarning = macosxSupport.tkVersionWarning(root)
1416 if tkversionwarning:
1417 shell.interp.runcommand(''.join(("print('", tkversionwarning, "')")))
1418
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001419 root.mainloop()
1420 root.destroy()
1421
David Scherer7aced172000-08-15 01:13:23 +00001422if __name__ == "__main__":
Kurt B. Kaiser9e8b8282003-06-15 17:38:45 +00001423 sys.modules['PyShell'] = sys.modules['__main__']
David Scherer7aced172000-08-15 01:13:23 +00001424 main()