blob: 33deb457a4b92f16159f2eaa8f2ed634a3c69e84 [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
Ned Deily7aff4512011-10-30 20:01:35 -0700343 self.original_compiler_flags = self.compile.compiler.flags
David Scherer7aced172000-08-15 01:13:23 +0000344
Chui Tey5d2af632002-05-26 13:36:41 +0000345 rpcclt = None
Ned Deilye5cad232011-08-02 18:47:13 -0700346 rpcsubproc = None
Chui Tey5d2af632002-05-26 13:36:41 +0000347
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000348 def spawn_subprocess(self):
Florent Xiclunafd1b0932010-03-28 00:25:02 +0000349 if self.subprocess_arglist is None:
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000350 self.subprocess_arglist = self.build_subprocess_arglist()
Ned Deilye5cad232011-08-02 18:47:13 -0700351 self.rpcsubproc = subprocess.Popen(self.subprocess_arglist)
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000352
Tony Lowndsf53dec22002-12-20 04:24:43 +0000353 def build_subprocess_arglist(self):
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000354 assert (self.port!=0), (
355 "Socket should have been assigned a port number.")
Tony Lownds2398d572003-05-13 15:28:21 +0000356 w = ['-W' + s for s in sys.warnoptions]
357 # Maybe IDLE is installed and is being accessed via sys.path,
358 # or maybe it's not installed and the idle.py script is being
359 # run from the IDLE source directory.
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000360 del_exitf = idleConf.GetOption('main', 'General', 'delete-exitfunc',
361 default=False, type='bool')
Tony Lownds2398d572003-05-13 15:28:21 +0000362 if __name__ == 'idlelib.PyShell':
Walter Dörwald70a6b492004-02-12 17:35:32 +0000363 command = "__import__('idlelib.run').run.main(%r)" % (del_exitf,)
Tony Lowndsf2324b92002-09-29 00:34:10 +0000364 else:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000365 command = "__import__('run').main(%r)" % (del_exitf,)
Ned Deilye5cad232011-08-02 18:47:13 -0700366 return [sys.executable] + w + ["-c", command, str(self.port)]
Tony Lowndsf2324b92002-09-29 00:34:10 +0000367
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000368 def start_subprocess(self):
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000369 addr = (HOST, self.port)
370 # GUI makes several attempts to acquire socket, listens for connection
Kurt B. Kaiser5db48432003-05-15 03:40:51 +0000371 for i in range(3):
Chui Tey5d2af632002-05-26 13:36:41 +0000372 time.sleep(i)
373 try:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000374 self.rpcclt = MyRPCClient(addr)
Chui Tey5d2af632002-05-26 13:36:41 +0000375 break
Guido van Rossumb940e112007-01-10 16:19:56 +0000376 except socket.error as err:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000377 pass
Chui Tey5d2af632002-05-26 13:36:41 +0000378 else:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000379 self.display_port_binding_error()
380 return None
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000381 # if PORT was 0, system will assign an 'ephemeral' port. Find it out:
382 self.port = self.rpcclt.listening_sock.getsockname()[1]
383 # if PORT was not 0, probably working with a remote execution server
384 if PORT != 0:
385 # To allow reconnection within the 2MSL wait (cf. Stevens TCP
386 # V1, 18.6), set SO_REUSEADDR. Note that this can be problematic
387 # on Windows since the implementation allows two active sockets on
388 # the same address!
389 self.rpcclt.listening_sock.setsockopt(socket.SOL_SOCKET,
390 socket.SO_REUSEADDR, 1)
391 self.spawn_subprocess()
392 #time.sleep(20) # test to simulate GUI not accepting connection
Kurt B. Kaiserb4179362002-07-26 00:06:42 +0000393 # Accept the connection from the Python execution server
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000394 self.rpcclt.listening_sock.settimeout(10)
395 try:
396 self.rpcclt.accept()
Guido van Rossumb940e112007-01-10 16:19:56 +0000397 except socket.timeout as err:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000398 self.display_no_subprocess_error()
399 return None
Kurt B. Kaiser969de452002-06-12 03:28:57 +0000400 self.rpcclt.register("stdin", self.tkconsole)
401 self.rpcclt.register("stdout", self.tkconsole.stdout)
402 self.rpcclt.register("stderr", self.tkconsole.stderr)
Chui Tey5d2af632002-05-26 13:36:41 +0000403 self.rpcclt.register("flist", self.tkconsole.flist)
Kurt B. Kaiser8cd0def2003-01-31 05:06:43 +0000404 self.rpcclt.register("linecache", linecache)
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000405 self.rpcclt.register("interp", self)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000406 self.transfer_path()
Chui Tey5d2af632002-05-26 13:36:41 +0000407 self.poll_subprocess()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000408 return self.rpcclt
Chui Tey5d2af632002-05-26 13:36:41 +0000409
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000410 def restart_subprocess(self):
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000411 if self.restarting:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000412 return self.rpcclt
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000413 self.restarting = True
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000414 # close only the subprocess debugger
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000415 debug = self.getdebugger()
416 if debug:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000417 try:
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000418 # Only close subprocess debugger, don't unregister gui_adap!
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000419 RemoteDebugger.close_subprocess_debugger(self.rpcclt)
420 except:
421 pass
422 # Kill subprocess, spawn a new one, accept connection.
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000423 self.rpcclt.close()
Ned Deilye5cad232011-08-02 18:47:13 -0700424 self.terminate_subprocess()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000425 console = self.tkconsole
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000426 was_executing = console.executing
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000427 console.executing = False
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000428 self.spawn_subprocess()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000429 try:
430 self.rpcclt.accept()
Guido van Rossumb940e112007-01-10 16:19:56 +0000431 except socket.timeout as err:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000432 self.display_no_subprocess_error()
433 return None
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000434 self.transfer_path()
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000435 # annotate restart in shell window and mark it
Kurt B. Kaiser4cc5ef52003-01-22 00:23:23 +0000436 console.text.delete("iomark", "end-1c")
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000437 if was_executing:
438 console.write('\n')
439 console.showprompt()
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000440 halfbar = ((int(console.width) - 16) // 2) * '='
441 console.write(halfbar + ' RESTART ' + halfbar)
442 console.text.mark_set("restart", "end-1c")
443 console.text.mark_gravity("restart", "left")
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000444 console.showprompt()
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000445 # restart subprocess debugger
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000446 if debug:
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000447 # Restarted debugger connects to current instance of debug GUI
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000448 gui = RemoteDebugger.restart_subprocess_debugger(self.rpcclt)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000449 # reload remote debugger breakpoints for all PyShellEditWindows
450 debug.load_breakpoints()
Ned Deily7aff4512011-10-30 20:01:35 -0700451 self.compile.compiler.flags = self.original_compiler_flags
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000452 self.restarting = False
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000453 return self.rpcclt
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000454
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000455 def __request_interrupt(self):
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000456 self.rpcclt.remotecall("exec", "interrupt_the_server", (), {})
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000457
458 def interrupt_subprocess(self):
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000459 threading.Thread(target=self.__request_interrupt).start()
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000460
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000461 def kill_subprocess(self):
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000462 try:
463 self.rpcclt.close()
464 except AttributeError: # no socket
465 pass
Ned Deilye5cad232011-08-02 18:47:13 -0700466 self.terminate_subprocess()
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000467 self.tkconsole.executing = False
468 self.rpcclt = None
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000469
Ned Deilye5cad232011-08-02 18:47:13 -0700470 def terminate_subprocess(self):
471 "Make sure subprocess is terminated"
472 try:
473 self.rpcsubproc.kill()
474 except OSError:
475 # process already terminated
476 return
477 else:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000478 try:
Ned Deilye5cad232011-08-02 18:47:13 -0700479 self.rpcsubproc.wait()
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000480 except OSError:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000481 return
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000482
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000483 def transfer_path(self):
484 self.runcommand("""if 1:
485 import sys as _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +0000486 _sys.path = %r
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000487 del _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +0000488 \n""" % (sys.path,))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000489
Chui Tey5d2af632002-05-26 13:36:41 +0000490 active_seq = None
491
492 def poll_subprocess(self):
493 clt = self.rpcclt
494 if clt is None:
495 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000496 try:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000497 response = clt.pollresponse(self.active_seq, wait=0.05)
498 except (EOFError, IOError, KeyboardInterrupt):
499 # lost connection or subprocess terminated itself, restart
500 # [the KBI is from rpc.SocketIO.handle_EOF()]
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000501 if self.tkconsole.closing:
502 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000503 response = None
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000504 self.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000505 if response:
506 self.tkconsole.resetoutput()
507 self.active_seq = None
508 how, what = response
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000509 console = self.tkconsole.console
Chui Tey5d2af632002-05-26 13:36:41 +0000510 if how == "OK":
511 if what is not None:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000512 print(repr(what), file=console)
Chui Tey5d2af632002-05-26 13:36:41 +0000513 elif how == "EXCEPTION":
Chui Tey5d2af632002-05-26 13:36:41 +0000514 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
515 self.remote_stack_viewer()
516 elif how == "ERROR":
Kurt B. Kaiser0930c432002-12-06 21:45:24 +0000517 errmsg = "PyShell.ModifiedInterpreter: Subprocess ERROR:\n"
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000518 print(errmsg, what, file=sys.__stderr__)
519 print(errmsg, what, file=console)
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000520 # we received a response to the currently active seq number:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000521 try:
522 self.tkconsole.endexecuting()
523 except AttributeError: # shell may have closed
524 pass
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000525 # Reschedule myself
526 if not self.tkconsole.closing:
527 self.tkconsole.text.after(self.tkconsole.pollinterval,
528 self.poll_subprocess)
Chui Tey5d2af632002-05-26 13:36:41 +0000529
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000530 debugger = None
531
532 def setdebugger(self, debugger):
533 self.debugger = debugger
534
535 def getdebugger(self):
536 return self.debugger
537
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000538 def open_remote_stack_viewer(self):
539 """Initiate the remote stack viewer from a separate thread.
540
541 This method is called from the subprocess, and by returning from this
542 method we allow the subprocess to unblock. After a bit the shell
543 requests the subprocess to open the remote stack viewer which returns a
Ezio Melotti60861182010-07-23 16:48:22 +0000544 static object looking at the last exception. It is queried through
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000545 the RPC mechanism.
546
547 """
548 self.tkconsole.text.after(300, self.remote_stack_viewer)
549 return
550
Chui Tey5d2af632002-05-26 13:36:41 +0000551 def remote_stack_viewer(self):
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000552 from idlelib import RemoteObjectBrowser
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000553 oid = self.rpcclt.remotequeue("exec", "stackviewer", ("flist",), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000554 if oid is None:
555 self.tkconsole.root.bell()
556 return
557 item = RemoteObjectBrowser.StubObjectTreeItem(self.rpcclt, oid)
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000558 from idlelib.TreeWidget import ScrolledCanvas, TreeNode
Chui Tey5d2af632002-05-26 13:36:41 +0000559 top = Toplevel(self.tkconsole.root)
Kurt B. Kaiser73360a32004-03-08 18:15:31 +0000560 theme = idleConf.GetOption('main','Theme','name')
561 background = idleConf.GetHighlight(theme, 'normal')['background']
562 sc = ScrolledCanvas(top, bg=background, highlightthickness=0)
Chui Tey5d2af632002-05-26 13:36:41 +0000563 sc.frame.pack(expand=1, fill="both")
564 node = TreeNode(sc.canvas, None, item)
565 node.expand()
566 # XXX Should GC the remote tree when closing the window
567
David Scherer7aced172000-08-15 01:13:23 +0000568 gid = 0
569
570 def execsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000571 "Like runsource() but assumes complete exec source"
David Scherer7aced172000-08-15 01:13:23 +0000572 filename = self.stuffsource(source)
573 self.execfile(filename, source)
574
575 def execfile(self, filename, source=None):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000576 "Execute an existing file"
David Scherer7aced172000-08-15 01:13:23 +0000577 if source is None:
Victor Stinner979482a2011-09-02 01:00:40 +0200578 with tokenize.open(filename) as fp:
Victor Stinner85c67722011-09-02 00:57:04 +0200579 source = fp.read()
David Scherer7aced172000-08-15 01:13:23 +0000580 try:
581 code = compile(source, filename, "exec")
582 except (OverflowError, SyntaxError):
583 self.tkconsole.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000584 tkerr = self.tkconsole.stderr
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000585 print('*** Error in script or command!\n', file=tkerr)
586 print('Traceback (most recent call last):', file=tkerr)
David Scherer7aced172000-08-15 01:13:23 +0000587 InteractiveInterpreter.showsyntaxerror(self, filename)
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000588 self.tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000589 else:
590 self.runcode(code)
591
592 def runsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000593 "Extend base class method: Stuff the source in the line cache first"
David Scherer7aced172000-08-15 01:13:23 +0000594 filename = self.stuffsource(source)
595 self.more = 0
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000596 self.save_warnings_filters = warnings.filters[:]
597 warnings.filterwarnings(action="error", category=SyntaxWarning)
Martin v. Löwis98ff8982007-08-13 06:03:15 +0000598 # at the moment, InteractiveInterpreter expects str
599 assert isinstance(source, str)
600 #if isinstance(source, str):
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000601 # from idlelib import IOBinding
Martin v. Löwis98ff8982007-08-13 06:03:15 +0000602 # try:
603 # source = source.encode(IOBinding.encoding)
604 # except UnicodeError:
605 # self.tkconsole.resetoutput()
606 # self.write("Unsupported characters in input\n")
607 # return
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000608 try:
Kurt B. Kaiser935ea9a2005-05-10 03:44:24 +0000609 # InteractiveInterpreter.runsource() calls its runcode() method,
610 # which is overridden (see below)
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000611 return InteractiveInterpreter.runsource(self, source, filename)
612 finally:
613 if self.save_warnings_filters is not None:
614 warnings.filters[:] = self.save_warnings_filters
615 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000616
617 def stuffsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000618 "Stuff source in the filename cache"
David Scherer7aced172000-08-15 01:13:23 +0000619 filename = "<pyshell#%d>" % self.gid
620 self.gid = self.gid + 1
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000621 lines = source.split("\n")
David Scherer7aced172000-08-15 01:13:23 +0000622 linecache.cache[filename] = len(source)+1, 0, lines, filename
623 return filename
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000624
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000625 def prepend_syspath(self, filename):
626 "Prepend sys.path with file's directory if not already included"
627 self.runcommand("""if 1:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000628 _filename = %r
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000629 import sys as _sys
630 from os.path import dirname as _dirname
631 _dir = _dirname(_filename)
632 if not _dir in _sys.path:
633 _sys.path.insert(0, _dir)
634 del _filename, _sys, _dirname, _dir
Walter Dörwald70a6b492004-02-12 17:35:32 +0000635 \n""" % (filename,))
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000636
David Scherer7aced172000-08-15 01:13:23 +0000637 def showsyntaxerror(self, filename=None):
Guido van Rossum33d26892007-08-05 15:29:28 +0000638 """Override Interactive Interpreter method: Use Colorizing
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000639
640 Color the offending position instead of printing it and pointing at it
641 with a caret.
642
643 """
Guido van Rossum33d26892007-08-05 15:29:28 +0000644 tkconsole = self.tkconsole
645 text = tkconsole.text
646 text.tag_remove("ERROR", "1.0", "end")
David Scherer7aced172000-08-15 01:13:23 +0000647 type, value, tb = sys.exc_info()
Ned Deily79746422011-09-14 14:49:14 -0700648 msg = getattr(value, 'msg', '') or value or "<no detail available>"
649 lineno = getattr(value, 'lineno', '') or 1
650 offset = getattr(value, 'offset', '') or 0
Guido van Rossum33d26892007-08-05 15:29:28 +0000651 if offset == 0:
652 lineno += 1 #mark end of offending line
653 if lineno == 1:
654 pos = "iomark + %d chars" % (offset-1)
David Scherer7aced172000-08-15 01:13:23 +0000655 else:
Guido van Rossum33d26892007-08-05 15:29:28 +0000656 pos = "iomark linestart + %d lines + %d chars" % \
657 (lineno-1, offset-1)
658 tkconsole.colorize_syntax_error(text, pos)
659 tkconsole.resetoutput()
660 self.write("SyntaxError: %s\n" % msg)
661 tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000662
663 def showtraceback(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000664 "Extend base class method to reset output properly"
David Scherer7aced172000-08-15 01:13:23 +0000665 self.tkconsole.resetoutput()
666 self.checklinecache()
667 InteractiveInterpreter.showtraceback(self)
Chui Tey5d2af632002-05-26 13:36:41 +0000668 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
669 self.tkconsole.open_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +0000670
671 def checklinecache(self):
672 c = linecache.cache
Guido van Rossum36e0a922007-07-20 04:05:57 +0000673 for key in list(c.keys()):
David Scherer7aced172000-08-15 01:13:23 +0000674 if key[:1] + key[-1:] != "<>":
675 del c[key]
676
Chui Tey5d2af632002-05-26 13:36:41 +0000677 def runcommand(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000678 "Run the code without invoking the debugger"
Chui Tey5d2af632002-05-26 13:36:41 +0000679 # The code better not raise an exception!
680 if self.tkconsole.executing:
Neal Norwitzf4c4f112002-11-30 18:49:10 +0000681 self.display_executing_dialog()
Chui Tey5d2af632002-05-26 13:36:41 +0000682 return 0
683 if self.rpcclt:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000684 self.rpcclt.remotequeue("exec", "runcode", (code,), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000685 else:
Georg Brandl7cae87c2006-09-06 06:51:57 +0000686 exec(code, self.locals)
Chui Tey5d2af632002-05-26 13:36:41 +0000687 return 1
688
David Scherer7aced172000-08-15 01:13:23 +0000689 def runcode(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000690 "Override base class method"
Chui Tey5d2af632002-05-26 13:36:41 +0000691 if self.tkconsole.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000692 self.interp.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000693 self.checklinecache()
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000694 if self.save_warnings_filters is not None:
695 warnings.filters[:] = self.save_warnings_filters
696 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000697 debugger = self.debugger
698 try:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000699 self.tkconsole.beginexecuting()
Thomas Wouterscf297e42007-02-23 15:07:44 +0000700 if not debugger and self.rpcclt is not None:
701 self.active_seq = self.rpcclt.asyncqueue("exec", "runcode",
702 (code,), {})
703 elif debugger:
704 debugger.run(code, self.locals)
705 else:
706 exec(code, self.locals)
707 except SystemExit:
708 if not self.tkconsole.closing:
709 if tkMessageBox.askyesno(
710 "Exit?",
711 "Do you want to exit altogether?",
712 default="yes",
713 master=self.tkconsole.text):
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000714 raise
Thomas Wouterscf297e42007-02-23 15:07:44 +0000715 else:
Guido van Rossum5dc0d972007-02-25 22:37:36 +0000716 self.showtraceback()
Thomas Wouterscf297e42007-02-23 15:07:44 +0000717 else:
718 raise
719 except:
720 if use_subprocess:
721 print("IDLE internal error in runcode()",
722 file=self.tkconsole.stderr)
David Scherer7aced172000-08-15 01:13:23 +0000723 self.showtraceback()
Thomas Wouterscf297e42007-02-23 15:07:44 +0000724 self.tkconsole.endexecuting()
725 else:
726 if self.tkconsole.canceled:
727 self.tkconsole.canceled = False
728 print("KeyboardInterrupt", file=self.tkconsole.stderr)
729 else:
730 self.showtraceback()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000731 finally:
732 if not use_subprocess:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000733 try:
734 self.tkconsole.endexecuting()
735 except AttributeError: # shell may have closed
736 pass
David Scherer7aced172000-08-15 01:13:23 +0000737
738 def write(self, s):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000739 "Override base class method"
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000740 self.tkconsole.stderr.write(s)
David Scherer7aced172000-08-15 01:13:23 +0000741
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000742 def display_port_binding_error(self):
743 tkMessageBox.showerror(
744 "Port Binding Error",
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000745 "IDLE can't bind to a TCP/IP port, which is necessary to "
746 "communicate with its Python execution server. This might be "
747 "because no networking is installed on this computer. "
748 "Run IDLE with the -n command line switch to start without a "
749 "subprocess and refer to Help/IDLE Help 'Running without a "
750 "subprocess' for further details.",
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000751 master=self.tkconsole.text)
752
753 def display_no_subprocess_error(self):
754 tkMessageBox.showerror(
755 "Subprocess Startup Error",
756 "IDLE's subprocess didn't make connection. Either IDLE can't "
757 "start a subprocess or personal firewall software is blocking "
758 "the connection.",
759 master=self.tkconsole.text)
760
761 def display_executing_dialog(self):
762 tkMessageBox.showerror(
763 "Already executing",
764 "The Python Shell window is already executing a command; "
765 "please wait until it is finished.",
766 master=self.tkconsole.text)
767
768
David Scherer7aced172000-08-15 01:13:23 +0000769class PyShell(OutputWindow):
770
771 shell_title = "Python Shell"
772
773 # Override classes
774 ColorDelegator = ModifiedColorDelegator
775 UndoDelegator = ModifiedUndoDelegator
776
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000777 # Override menus
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000778 menu_specs = [
779 ("file", "_File"),
780 ("edit", "_Edit"),
Kurt B. Kaiser4cc5ef52003-01-22 00:23:23 +0000781 ("debug", "_Debug"),
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000782 ("options", "_Options"),
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000783 ("windows", "_Windows"),
784 ("help", "_Help"),
785 ]
David Scherer7aced172000-08-15 01:13:23 +0000786
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000787 if macosxSupport.runningAsOSXApp():
788 del menu_specs[-3]
789 menu_specs[-2] = ("windows", "_Window")
790
791
David Scherer7aced172000-08-15 01:13:23 +0000792 # New classes
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000793 from idlelib.IdleHistory import History
David Scherer7aced172000-08-15 01:13:23 +0000794
795 def __init__(self, flist=None):
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000796 if use_subprocess:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000797 ms = self.menu_specs
798 if ms[2][0] != "shell":
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000799 ms.insert(2, ("shell", "She_ll"))
David Scherer7aced172000-08-15 01:13:23 +0000800 self.interp = ModifiedInterpreter(self)
801 if flist is None:
802 root = Tk()
803 fixwordbreaks(root)
804 root.withdraw()
805 flist = PyShellFileList(root)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000806 #
David Scherer7aced172000-08-15 01:13:23 +0000807 OutputWindow.__init__(self, flist, None, None)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000808 #
Kurt B. Kaiser6af44982005-01-19 00:22:59 +0000809## self.config(usetabs=1, indentwidth=8, context_use_ps1=1)
810 self.usetabs = True
811 # indentwidth must be 8 when using tabs. See note in EditorWindow:
812 self.indentwidth = 8
813 self.context_use_ps1 = True
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000814 #
David Scherer7aced172000-08-15 01:13:23 +0000815 text = self.text
816 text.configure(wrap="char")
817 text.bind("<<newline-and-indent>>", self.enter_callback)
818 text.bind("<<plain-newline-and-indent>>", self.linefeed_callback)
819 text.bind("<<interrupt-execution>>", self.cancel_callback)
David Scherer7aced172000-08-15 01:13:23 +0000820 text.bind("<<end-of-file>>", self.eof_callback)
821 text.bind("<<open-stack-viewer>>", self.open_stack_viewer)
Kurt B. Kaiser57bfe5d2003-05-10 00:09:52 +0000822 text.bind("<<toggle-debugger>>", self.toggle_debugger)
David Scherer7aced172000-08-15 01:13:23 +0000823 text.bind("<<toggle-jit-stack-viewer>>", self.toggle_jit_stack_viewer)
Kurt B. Kaiser8a78cad2007-12-13 03:38:16 +0000824 self.color = color = self.ColorDelegator()
825 self.per.insertfilter(color)
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000826 if use_subprocess:
827 text.bind("<<view-restart>>", self.view_restart_mark)
828 text.bind("<<restart-shell>>", self.restart_shell)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000829 #
David Scherer7aced172000-08-15 01:13:23 +0000830 self.save_stdout = sys.stdout
831 self.save_stderr = sys.stderr
832 self.save_stdin = sys.stdin
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000833 from idlelib import IOBinding
Martin v. Löwisbcc651a2003-06-22 07:52:56 +0000834 self.stdout = PseudoFile(self, "stdout", IOBinding.encoding)
835 self.stderr = PseudoFile(self, "stderr", IOBinding.encoding)
836 self.console = PseudoFile(self, "console", IOBinding.encoding)
Chui Tey5d2af632002-05-26 13:36:41 +0000837 if not use_subprocess:
838 sys.stdout = self.stdout
Kurt B. Kaiser7cec2522007-08-31 04:15:13 +0000839 sys.stderr = self.stderr
Chui Tey5d2af632002-05-26 13:36:41 +0000840 sys.stdin = self
Kurt B. Kaiserf609a342007-12-28 03:57:56 +0000841 try:
842 # page help() text to shell.
843 import pydoc # import must be done here to capture i/o rebinding.
844 # XXX KBK 27Dec07 use a textView someday, but must work w/o subproc
845 pydoc.pager = pydoc.plainpager
846 except:
847 sys.stderr = sys.__stderr__
848 raise
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000849 #
David Scherer7aced172000-08-15 01:13:23 +0000850 self.history = self.History(self.text)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000851 #
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000852 self.pollinterval = 50 # millisec
Chui Tey5d2af632002-05-26 13:36:41 +0000853
Kurt B. Kaiser4d5bc602004-06-06 01:29:22 +0000854 def get_standard_extension_names(self):
855 return idleConf.GetExtensions(shell_only=True)
856
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000857 reading = False
858 executing = False
859 canceled = False
860 endoffile = False
861 closing = False
David Scherer7aced172000-08-15 01:13:23 +0000862
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +0000863 def set_warning_stream(self, stream):
Skip Montanarod9161422004-07-06 21:53:27 +0000864 global warning_stream
865 warning_stream = stream
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +0000866
867 def get_warning_stream(self):
868 return warning_stream
869
David Scherer7aced172000-08-15 01:13:23 +0000870 def toggle_debugger(self, event=None):
871 if self.executing:
872 tkMessageBox.showerror("Don't debug now",
873 "You can only toggle the debugger when idle",
874 master=self.text)
875 self.set_debugger_indicator()
876 return "break"
877 else:
878 db = self.interp.getdebugger()
879 if db:
880 self.close_debugger()
881 else:
882 self.open_debugger()
883
884 def set_debugger_indicator(self):
885 db = self.interp.getdebugger()
886 self.setvar("<<toggle-debugger>>", not not db)
887
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000888 def toggle_jit_stack_viewer(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +0000889 pass # All we need is the variable
890
891 def close_debugger(self):
892 db = self.interp.getdebugger()
893 if db:
894 self.interp.setdebugger(None)
895 db.close()
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000896 if self.interp.rpcclt:
897 RemoteDebugger.close_remote_debugger(self.interp.rpcclt)
David Scherer7aced172000-08-15 01:13:23 +0000898 self.resetoutput()
899 self.console.write("[DEBUG OFF]\n")
900 sys.ps1 = ">>> "
901 self.showprompt()
902 self.set_debugger_indicator()
903
904 def open_debugger(self):
Chui Tey5d2af632002-05-26 13:36:41 +0000905 if self.interp.rpcclt:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000906 dbg_gui = RemoteDebugger.start_remote_debugger(self.interp.rpcclt,
907 self)
908 else:
909 dbg_gui = Debugger.Debugger(self)
910 self.interp.setdebugger(dbg_gui)
911 dbg_gui.load_breakpoints()
Chui Tey5d2af632002-05-26 13:36:41 +0000912 sys.ps1 = "[DEBUG ON]\n>>> "
913 self.showprompt()
914 self.set_debugger_indicator()
915
David Scherer7aced172000-08-15 01:13:23 +0000916 def beginexecuting(self):
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000917 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +0000918 self.resetoutput()
919 self.executing = 1
David Scherer7aced172000-08-15 01:13:23 +0000920
921 def endexecuting(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000922 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +0000923 self.executing = 0
924 self.canceled = 0
Chui Tey5d2af632002-05-26 13:36:41 +0000925 self.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000926
927 def close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000928 "Extend EditorWindow.close()"
David Scherer7aced172000-08-15 01:13:23 +0000929 if self.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000930 response = tkMessageBox.askokcancel(
David Scherer7aced172000-08-15 01:13:23 +0000931 "Kill?",
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000932 "The program is still running!\n Do you want to kill it?",
David Scherer7aced172000-08-15 01:13:23 +0000933 default="ok",
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000934 parent=self.text)
Benjamin Peterson2a691a82008-03-31 01:51:45 +0000935 if response is False:
David Scherer7aced172000-08-15 01:13:23 +0000936 return "cancel"
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +0000937 if self.reading:
938 self.top.quit()
939 self.canceled = True
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000940 self.closing = True
941 # Wait for poll_subprocess() rescheduling to stop
942 self.text.after(2 * self.pollinterval, self.close2)
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000943
944 def close2(self):
945 return EditorWindow.close(self)
David Scherer7aced172000-08-15 01:13:23 +0000946
947 def _close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000948 "Extend EditorWindow._close(), shut down debugger and execution server"
David Scherer7aced172000-08-15 01:13:23 +0000949 self.close_debugger()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000950 if use_subprocess:
951 self.interp.kill_subprocess()
David Scherer7aced172000-08-15 01:13:23 +0000952 # Restore std streams
953 sys.stdout = self.save_stdout
954 sys.stderr = self.save_stderr
955 sys.stdin = self.save_stdin
956 # Break cycles
957 self.interp = None
958 self.console = None
David Scherer7aced172000-08-15 01:13:23 +0000959 self.flist.pyshell = None
960 self.history = None
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000961 EditorWindow._close(self)
David Scherer7aced172000-08-15 01:13:23 +0000962
963 def ispythonsource(self, filename):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000964 "Override EditorWindow method: never remove the colorizer"
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000965 return True
David Scherer7aced172000-08-15 01:13:23 +0000966
967 def short_title(self):
968 return self.shell_title
969
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000970 COPYRIGHT = \
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000971 'Type "copyright", "credits" or "license()" for more information.'
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000972
David Scherer7aced172000-08-15 01:13:23 +0000973 def begin(self):
Kurt B. Kaiser7378df72007-08-11 04:20:51 +0000974 self.text.mark_set("iomark", "insert")
David Scherer7aced172000-08-15 01:13:23 +0000975 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000976 if use_subprocess:
977 nosub = ''
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000978 client = self.interp.start_subprocess()
979 if not client:
980 self.close()
Kurt B. Kaiser76637292004-01-21 22:10:01 +0000981 return False
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000982 else:
983 nosub = "==== No Subprocess ===="
Raymond Hettingera2a8e8b2009-01-27 00:28:36 +0000984 self.write("Python %s on %s\n%s\n%s" %
985 (sys.version, sys.platform, self.COPYRIGHT, nosub))
David Scherer7aced172000-08-15 01:13:23 +0000986 self.showprompt()
Georg Brandl14fc4272008-05-17 18:39:55 +0000987 import tkinter
988 tkinter._default_root = None # 03Jan04 KBK What's this?
Kurt B. Kaiser76637292004-01-21 22:10:01 +0000989 return True
David Scherer7aced172000-08-15 01:13:23 +0000990
991 def readline(self):
992 save = self.reading
993 try:
994 self.reading = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +0000995 self.top.mainloop() # nested mainloop()
David Scherer7aced172000-08-15 01:13:23 +0000996 finally:
997 self.reading = save
998 line = self.text.get("iomark", "end-1c")
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +0000999 if len(line) == 0: # may be EOF if we quit our mainloop with Ctrl-C
1000 line = "\n"
David Scherer7aced172000-08-15 01:13:23 +00001001 self.resetoutput()
1002 if self.canceled:
1003 self.canceled = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001004 if not use_subprocess:
1005 raise KeyboardInterrupt
David Scherer7aced172000-08-15 01:13:23 +00001006 if self.endoffile:
1007 self.endoffile = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001008 line = ""
David Scherer7aced172000-08-15 01:13:23 +00001009 return line
1010
1011 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001012 return True
David Scherer7aced172000-08-15 01:13:23 +00001013
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001014 def cancel_callback(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +00001015 try:
1016 if self.text.compare("sel.first", "!=", "sel.last"):
1017 return # Active selection -- always use default binding
1018 except:
1019 pass
1020 if not (self.executing or self.reading):
1021 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001022 self.interp.write("KeyboardInterrupt\n")
David Scherer7aced172000-08-15 01:13:23 +00001023 self.showprompt()
1024 return "break"
1025 self.endoffile = 0
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001026 self.canceled = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001027 if (self.executing and self.interp.rpcclt):
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +00001028 if self.interp.getdebugger():
1029 self.interp.restart_subprocess()
1030 else:
1031 self.interp.interrupt_subprocess()
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001032 if self.reading:
1033 self.top.quit() # exit the nested mainloop() in readline()
David Scherer7aced172000-08-15 01:13:23 +00001034 return "break"
1035
1036 def eof_callback(self, event):
1037 if self.executing and not self.reading:
1038 return # Let the default binding (delete next char) take over
1039 if not (self.text.compare("iomark", "==", "insert") and
1040 self.text.compare("insert", "==", "end-1c")):
1041 return # Let the default binding (delete next char) take over
1042 if not self.executing:
David Scherer7aced172000-08-15 01:13:23 +00001043 self.resetoutput()
1044 self.close()
1045 else:
1046 self.canceled = 0
1047 self.endoffile = 1
1048 self.top.quit()
1049 return "break"
1050
David Scherer7aced172000-08-15 01:13:23 +00001051 def linefeed_callback(self, event):
1052 # Insert a linefeed without entering anything (still autoindented)
1053 if self.reading:
1054 self.text.insert("insert", "\n")
1055 self.text.see("insert")
1056 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001057 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001058 return "break"
1059
1060 def enter_callback(self, event):
1061 if self.executing and not self.reading:
1062 return # Let the default binding (insert '\n') take over
1063 # If some text is selected, recall the selection
1064 # (but only if this before the I/O mark)
1065 try:
1066 sel = self.text.get("sel.first", "sel.last")
1067 if sel:
1068 if self.text.compare("sel.last", "<=", "iomark"):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001069 self.recall(sel, event)
David Scherer7aced172000-08-15 01:13:23 +00001070 return "break"
1071 except:
1072 pass
1073 # If we're strictly before the line containing iomark, recall
1074 # the current line, less a leading prompt, less leading or
1075 # trailing whitespace
1076 if self.text.compare("insert", "<", "iomark linestart"):
1077 # Check if there's a relevant stdin range -- if so, use it
1078 prev = self.text.tag_prevrange("stdin", "insert")
1079 if prev and self.text.compare("insert", "<", prev[1]):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001080 self.recall(self.text.get(prev[0], prev[1]), event)
David Scherer7aced172000-08-15 01:13:23 +00001081 return "break"
1082 next = self.text.tag_nextrange("stdin", "insert")
1083 if next and self.text.compare("insert lineend", ">=", next[0]):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001084 self.recall(self.text.get(next[0], next[1]), event)
David Scherer7aced172000-08-15 01:13:23 +00001085 return "break"
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001086 # No stdin mark -- just get the current line, less any prompt
Kurt B. Kaiserb1754452005-11-18 22:05:48 +00001087 indices = self.text.tag_nextrange("console", "insert linestart")
1088 if indices and \
1089 self.text.compare(indices[0], "<=", "insert linestart"):
1090 self.recall(self.text.get(indices[1], "insert lineend"), event)
1091 else:
1092 self.recall(self.text.get("insert linestart", "insert lineend"), event)
David Scherer7aced172000-08-15 01:13:23 +00001093 return "break"
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001094 # If we're between the beginning of the line and the iomark, i.e.
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001095 # in the prompt area, move to the end of the prompt
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001096 if self.text.compare("insert", "<", "iomark"):
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001097 self.text.mark_set("insert", "iomark")
David Scherer7aced172000-08-15 01:13:23 +00001098 # If we're in the current input and there's only whitespace
1099 # beyond the cursor, erase that whitespace first
1100 s = self.text.get("insert", "end-1c")
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001101 if s and not s.strip():
David Scherer7aced172000-08-15 01:13:23 +00001102 self.text.delete("insert", "end-1c")
1103 # If we're in the current input before its last line,
1104 # insert a newline right at the insert point
1105 if self.text.compare("insert", "<", "end-1c linestart"):
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001106 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001107 return "break"
1108 # We're in the last line; append a newline and submit it
1109 self.text.mark_set("insert", "end-1c")
1110 if self.reading:
1111 self.text.insert("insert", "\n")
1112 self.text.see("insert")
1113 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001114 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001115 self.text.tag_add("stdin", "iomark", "end-1c")
1116 self.text.update_idletasks()
1117 if self.reading:
Neal Norwitzce96f692006-03-17 06:49:51 +00001118 self.top.quit() # Break out of recursive mainloop()
David Scherer7aced172000-08-15 01:13:23 +00001119 else:
1120 self.runit()
1121 return "break"
1122
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001123 def recall(self, s, event):
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001124 # remove leading and trailing empty or whitespace lines
1125 s = re.sub(r'^\s*\n', '' , s)
1126 s = re.sub(r'\n\s*$', '', s)
1127 lines = s.split('\n')
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001128 self.text.undo_block_start()
1129 try:
1130 self.text.tag_remove("sel", "1.0", "end")
1131 self.text.mark_set("insert", "end-1c")
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001132 prefix = self.text.get("insert linestart", "insert")
1133 if prefix.rstrip().endswith(':'):
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001134 self.newline_and_indent_event(event)
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001135 prefix = self.text.get("insert linestart", "insert")
1136 self.text.insert("insert", lines[0].strip())
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001137 if len(lines) > 1:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001138 orig_base_indent = re.search(r'^([ \t]*)', lines[0]).group(0)
1139 new_base_indent = re.search(r'^([ \t]*)', prefix).group(0)
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001140 for line in lines[1:]:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001141 if line.startswith(orig_base_indent):
1142 # replace orig base indentation with new indentation
1143 line = new_base_indent + line[len(orig_base_indent):]
1144 self.text.insert('insert', '\n'+line.rstrip())
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001145 finally:
1146 self.text.see("insert")
1147 self.text.undo_block_stop()
David Scherer7aced172000-08-15 01:13:23 +00001148
1149 def runit(self):
1150 line = self.text.get("iomark", "end-1c")
1151 # Strip off last newline and surrounding whitespace.
1152 # (To allow you to hit return twice to end a statement.)
1153 i = len(line)
1154 while i > 0 and line[i-1] in " \t":
1155 i = i-1
1156 if i > 0 and line[i-1] == "\n":
1157 i = i-1
1158 while i > 0 and line[i-1] in " \t":
1159 i = i-1
1160 line = line[:i]
1161 more = self.interp.runsource(line)
David Scherer7aced172000-08-15 01:13:23 +00001162
David Scherer7aced172000-08-15 01:13:23 +00001163 def open_stack_viewer(self, event=None):
Chui Tey5d2af632002-05-26 13:36:41 +00001164 if self.interp.rpcclt:
1165 return self.interp.remote_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +00001166 try:
1167 sys.last_traceback
1168 except:
1169 tkMessageBox.showerror("No stack trace",
1170 "There is no stack trace yet.\n"
1171 "(sys.last_traceback is not defined)",
1172 master=self.text)
1173 return
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +00001174 from idlelib.StackViewer import StackBrowser
David Scherer7aced172000-08-15 01:13:23 +00001175 sv = StackBrowser(self.root, self.flist)
1176
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001177 def view_restart_mark(self, event=None):
1178 self.text.see("iomark")
1179 self.text.see("restart")
1180
1181 def restart_shell(self, event=None):
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +00001182 self.interp.restart_subprocess()
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001183
David Scherer7aced172000-08-15 01:13:23 +00001184 def showprompt(self):
1185 self.resetoutput()
1186 try:
1187 s = str(sys.ps1)
1188 except:
1189 s = ""
1190 self.console.write(s)
1191 self.text.mark_set("insert", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001192 self.set_line_and_column()
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +00001193 self.io.reset_undo()
David Scherer7aced172000-08-15 01:13:23 +00001194
1195 def resetoutput(self):
1196 source = self.text.get("iomark", "end-1c")
1197 if self.history:
1198 self.history.history_store(source)
1199 if self.text.get("end-2c") != "\n":
1200 self.text.insert("end-1c", "\n")
1201 self.text.mark_set("iomark", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001202 self.set_line_and_column()
David Scherer7aced172000-08-15 01:13:23 +00001203
1204 def write(self, s, tags=()):
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001205 try:
1206 self.text.mark_gravity("iomark", "right")
1207 OutputWindow.write(self, s, tags, "iomark")
1208 self.text.mark_gravity("iomark", "left")
1209 except:
Kurt B. Kaisercbbe98f2007-08-12 01:52:35 +00001210 raise ###pass # ### 11Aug07 KBK if we are expecting exceptions
1211 # let's find out what they are and be specific.
David Scherer7aced172000-08-15 01:13:23 +00001212 if self.canceled:
1213 self.canceled = 0
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001214 if not use_subprocess:
1215 raise KeyboardInterrupt
David Scherer7aced172000-08-15 01:13:23 +00001216
Kurt B. Kaiserdcba6622004-12-21 22:10:32 +00001217class PseudoFile(object):
David Scherer7aced172000-08-15 01:13:23 +00001218
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001219 def __init__(self, shell, tags, encoding=None):
David Scherer7aced172000-08-15 01:13:23 +00001220 self.shell = shell
1221 self.tags = tags
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001222 self.encoding = encoding
David Scherer7aced172000-08-15 01:13:23 +00001223
1224 def write(self, s):
1225 self.shell.write(s, self.tags)
1226
Kurt B. Kaiser66aaf742007-08-09 18:00:23 +00001227 def writelines(self, lines):
1228 for line in lines:
1229 self.write(line)
David Scherer7aced172000-08-15 01:13:23 +00001230
1231 def flush(self):
1232 pass
1233
1234 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001235 return True
David Scherer7aced172000-08-15 01:13:23 +00001236
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001237
David Scherer7aced172000-08-15 01:13:23 +00001238usage_msg = """\
David Scherer7aced172000-08-15 01:13:23 +00001239
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001240USAGE: idle [-deins] [-t title] [file]*
1241 idle [-dns] [-t title] (-c cmd | -r file) [arg]*
1242 idle [-dns] [-t title] - [arg]*
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001243
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001244 -h print this help message and exit
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001245 -n run IDLE without a subprocess (see Help/IDLE Help for details)
David Scherer7aced172000-08-15 01:13:23 +00001246
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001247The following options will override the IDLE 'settings' configuration:
Kurt B. Kaiser96d88422001-07-17 04:59:01 +00001248
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001249 -e open an edit window
1250 -i open a shell window
1251
1252The following options imply -i and will open a shell:
1253
1254 -c cmd run the command in a shell, or
1255 -r file run script from file
1256
1257 -d enable the debugger
1258 -s run $IDLESTARTUP or $PYTHONSTARTUP before anything else
1259 -t title set title of shell window
1260
1261A default edit window will be bypassed when -c, -r, or - are used.
1262
1263[arg]* are passed to the command (-c) or script (-r) in sys.argv[1:].
1264
1265Examples:
1266
1267idle
1268 Open an edit window or shell depending on IDLE's configuration.
1269
1270idle foo.py foobar.py
1271 Edit the files, also open a shell if configured to start with shell.
1272
1273idle -est "Baz" foo.py
1274 Run $IDLESTARTUP or $PYTHONSTARTUP, edit foo.py, and open a shell
1275 window with the title "Baz".
1276
Neal Norwitz752abd02008-05-13 04:55:24 +00001277idle -c "import sys; print(sys.argv)" "foo"
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001278 Open a shell window and run the command, passing "-c" in sys.argv[0]
1279 and "foo" in sys.argv[1].
1280
1281idle -d -s -r foo.py "Hello World"
1282 Open a shell window, run a startup script, enable the debugger, and
1283 run foo.py, passing "foo.py" in sys.argv[0] and "Hello World" in
1284 sys.argv[1].
1285
Neal Norwitz752abd02008-05-13 04:55:24 +00001286echo "import sys; print(sys.argv)" | idle - "foobar"
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001287 Open a shell window, run the script piped in, passing '' in sys.argv[0]
1288 and "foobar" in sys.argv[1].
David Scherer7aced172000-08-15 01:13:23 +00001289"""
1290
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001291def main():
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001292 global flist, root, use_subprocess
David Scherer7aced172000-08-15 01:13:23 +00001293
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001294 use_subprocess = True
Kurt B. Kaisere866c812009-04-04 21:07:39 +00001295 enable_shell = True
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001296 enable_edit = False
1297 debug = False
1298 cmd = None
1299 script = None
1300 startup = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001301 try:
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001302 opts, args = getopt.getopt(sys.argv[1:], "c:deihnr:st:")
Guido van Rossumb940e112007-01-10 16:19:56 +00001303 except getopt.error as msg:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001304 sys.stderr.write("Error: %s\n" % str(msg))
1305 sys.stderr.write(usage_msg)
1306 sys.exit(2)
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001307 for o, a in opts:
1308 if o == '-c':
1309 cmd = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001310 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001311 if o == '-d':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001312 debug = True
1313 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001314 if o == '-e':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001315 enable_edit = True
Kurt B. Kaisere866c812009-04-04 21:07:39 +00001316 enable_shell = False
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001317 if o == '-h':
1318 sys.stdout.write(usage_msg)
1319 sys.exit()
1320 if o == '-i':
1321 enable_shell = True
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001322 if o == '-n':
1323 use_subprocess = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001324 if o == '-r':
1325 script = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001326 if os.path.isfile(script):
1327 pass
1328 else:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001329 print("No script file: ", script)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001330 sys.exit()
1331 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001332 if o == '-s':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001333 startup = True
1334 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001335 if o == '-t':
1336 PyShell.shell_title = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001337 enable_shell = True
1338 if args and args[0] == '-':
1339 cmd = sys.stdin.read()
1340 enable_shell = True
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001341 # process sys.argv and sys.path:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001342 for i in range(len(sys.path)):
1343 sys.path[i] = os.path.abspath(sys.path[i])
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001344 if args and args[0] == '-':
1345 sys.argv = [''] + args[1:]
1346 elif cmd:
1347 sys.argv = ['-c'] + args
1348 elif script:
1349 sys.argv = [script] + args
1350 elif args:
1351 enable_edit = True
1352 pathx = []
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001353 for filename in args:
1354 pathx.append(os.path.dirname(filename))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001355 for dir in pathx:
1356 dir = os.path.abspath(dir)
1357 if not dir in sys.path:
1358 sys.path.insert(0, dir)
Kurt B. Kaiserff002b92002-12-21 21:39:11 +00001359 else:
Neal Norwitzd082b6e2007-08-26 23:37:53 +00001360 dir = os.getcwd()
1361 if dir not in sys.path:
Kurt B. Kaiserff002b92002-12-21 21:39:11 +00001362 sys.path.insert(0, dir)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001363 # check the IDLE settings configuration (but command line overrides)
1364 edit_start = idleConf.GetOption('main', 'General',
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001365 'editor-on-startup', type='bool')
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001366 enable_edit = enable_edit or edit_start
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001367 # start editor and/or shell windows:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001368 root = Tk(className="Idle")
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001369
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001370 fixwordbreaks(root)
1371 root.withdraw()
1372 flist = PyShellFileList(root)
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001373 macosxSupport.setupApp(root, flist)
1374
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001375 if enable_edit:
1376 if not (cmd or script):
1377 for filename in args:
1378 flist.open(filename)
1379 if not args:
1380 flist.new()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001381 if enable_shell:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001382 shell = flist.open_shell()
1383 if not shell:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001384 return # couldn't open shell
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001385
1386 if macosxSupport.runningAsOSXApp() and flist.dict:
1387 # On OSX: when the user has double-clicked on a file that causes
1388 # IDLE to be launched the shell window will open just in front of
1389 # the file she wants to see. Lower the interpreter window when
1390 # there are open files.
1391 shell.top.lower()
1392
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001393 shell = flist.pyshell
1394 # handle remaining options:
1395 if debug:
1396 shell.open_debugger()
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001397 if startup:
1398 filename = os.environ.get("IDLESTARTUP") or \
1399 os.environ.get("PYTHONSTARTUP")
1400 if filename and os.path.isfile(filename):
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001401 shell.interp.execfile(filename)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001402 if shell and cmd or script:
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001403 shell.interp.runcommand("""if 1:
1404 import sys as _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001405 _sys.argv = %r
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001406 del _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001407 \n""" % (sys.argv,))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001408 if cmd:
1409 shell.interp.execsource(cmd)
1410 elif script:
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001411 shell.interp.prepend_syspath(script)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001412 shell.interp.execfile(script)
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001413
Ned Deily4ce92b22011-01-15 04:37:12 +00001414 # Check for problematic OS X Tk versions and print a warning message
1415 # in the IDLE shell window; this is less intrusive than always opening
1416 # a separate window.
1417 tkversionwarning = macosxSupport.tkVersionWarning(root)
1418 if tkversionwarning:
1419 shell.interp.runcommand(''.join(("print('", tkversionwarning, "')")))
1420
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001421 root.mainloop()
1422 root.destroy()
1423
David Scherer7aced172000-08-15 01:13:23 +00001424if __name__ == "__main__":
Kurt B. Kaiser9e8b8282003-06-15 17:38:45 +00001425 sys.modules['PyShell'] = sys.modules['__main__']
David Scherer7aced172000-08-15 01:13:23 +00001426 main()