blob: ea3a5d9a8e1cd9e0c8b7de4eda3b3631f451a177 [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:
Ned Deily55f87572011-11-05 22:36:44 -0700463 self.rpcclt.listening_sock.close()
464 except AttributeError: # no socket
465 pass
466 try:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000467 self.rpcclt.close()
468 except AttributeError: # no socket
469 pass
Ned Deilye5cad232011-08-02 18:47:13 -0700470 self.terminate_subprocess()
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000471 self.tkconsole.executing = False
472 self.rpcclt = None
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000473
Ned Deilye5cad232011-08-02 18:47:13 -0700474 def terminate_subprocess(self):
475 "Make sure subprocess is terminated"
476 try:
477 self.rpcsubproc.kill()
478 except OSError:
479 # process already terminated
480 return
481 else:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000482 try:
Ned Deilye5cad232011-08-02 18:47:13 -0700483 self.rpcsubproc.wait()
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000484 except OSError:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000485 return
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000486
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000487 def transfer_path(self):
488 self.runcommand("""if 1:
489 import sys as _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +0000490 _sys.path = %r
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000491 del _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +0000492 \n""" % (sys.path,))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000493
Chui Tey5d2af632002-05-26 13:36:41 +0000494 active_seq = None
495
496 def poll_subprocess(self):
497 clt = self.rpcclt
498 if clt is None:
499 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000500 try:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000501 response = clt.pollresponse(self.active_seq, wait=0.05)
502 except (EOFError, IOError, KeyboardInterrupt):
503 # lost connection or subprocess terminated itself, restart
504 # [the KBI is from rpc.SocketIO.handle_EOF()]
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000505 if self.tkconsole.closing:
506 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000507 response = None
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000508 self.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000509 if response:
510 self.tkconsole.resetoutput()
511 self.active_seq = None
512 how, what = response
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000513 console = self.tkconsole.console
Chui Tey5d2af632002-05-26 13:36:41 +0000514 if how == "OK":
515 if what is not None:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000516 print(repr(what), file=console)
Chui Tey5d2af632002-05-26 13:36:41 +0000517 elif how == "EXCEPTION":
Chui Tey5d2af632002-05-26 13:36:41 +0000518 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
519 self.remote_stack_viewer()
520 elif how == "ERROR":
Kurt B. Kaiser0930c432002-12-06 21:45:24 +0000521 errmsg = "PyShell.ModifiedInterpreter: Subprocess ERROR:\n"
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000522 print(errmsg, what, file=sys.__stderr__)
523 print(errmsg, what, file=console)
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000524 # we received a response to the currently active seq number:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000525 try:
526 self.tkconsole.endexecuting()
527 except AttributeError: # shell may have closed
528 pass
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000529 # Reschedule myself
530 if not self.tkconsole.closing:
531 self.tkconsole.text.after(self.tkconsole.pollinterval,
532 self.poll_subprocess)
Chui Tey5d2af632002-05-26 13:36:41 +0000533
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000534 debugger = None
535
536 def setdebugger(self, debugger):
537 self.debugger = debugger
538
539 def getdebugger(self):
540 return self.debugger
541
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000542 def open_remote_stack_viewer(self):
543 """Initiate the remote stack viewer from a separate thread.
544
545 This method is called from the subprocess, and by returning from this
546 method we allow the subprocess to unblock. After a bit the shell
547 requests the subprocess to open the remote stack viewer which returns a
Ezio Melotti60861182010-07-23 16:48:22 +0000548 static object looking at the last exception. It is queried through
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000549 the RPC mechanism.
550
551 """
552 self.tkconsole.text.after(300, self.remote_stack_viewer)
553 return
554
Chui Tey5d2af632002-05-26 13:36:41 +0000555 def remote_stack_viewer(self):
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000556 from idlelib import RemoteObjectBrowser
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000557 oid = self.rpcclt.remotequeue("exec", "stackviewer", ("flist",), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000558 if oid is None:
559 self.tkconsole.root.bell()
560 return
561 item = RemoteObjectBrowser.StubObjectTreeItem(self.rpcclt, oid)
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000562 from idlelib.TreeWidget import ScrolledCanvas, TreeNode
Chui Tey5d2af632002-05-26 13:36:41 +0000563 top = Toplevel(self.tkconsole.root)
Kurt B. Kaiser73360a32004-03-08 18:15:31 +0000564 theme = idleConf.GetOption('main','Theme','name')
565 background = idleConf.GetHighlight(theme, 'normal')['background']
566 sc = ScrolledCanvas(top, bg=background, highlightthickness=0)
Chui Tey5d2af632002-05-26 13:36:41 +0000567 sc.frame.pack(expand=1, fill="both")
568 node = TreeNode(sc.canvas, None, item)
569 node.expand()
570 # XXX Should GC the remote tree when closing the window
571
David Scherer7aced172000-08-15 01:13:23 +0000572 gid = 0
573
574 def execsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000575 "Like runsource() but assumes complete exec source"
David Scherer7aced172000-08-15 01:13:23 +0000576 filename = self.stuffsource(source)
577 self.execfile(filename, source)
578
579 def execfile(self, filename, source=None):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000580 "Execute an existing file"
David Scherer7aced172000-08-15 01:13:23 +0000581 if source is None:
Victor Stinner979482a2011-09-02 01:00:40 +0200582 with tokenize.open(filename) as fp:
Victor Stinner85c67722011-09-02 00:57:04 +0200583 source = fp.read()
David Scherer7aced172000-08-15 01:13:23 +0000584 try:
585 code = compile(source, filename, "exec")
586 except (OverflowError, SyntaxError):
587 self.tkconsole.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000588 tkerr = self.tkconsole.stderr
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000589 print('*** Error in script or command!\n', file=tkerr)
590 print('Traceback (most recent call last):', file=tkerr)
David Scherer7aced172000-08-15 01:13:23 +0000591 InteractiveInterpreter.showsyntaxerror(self, filename)
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000592 self.tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000593 else:
594 self.runcode(code)
595
596 def runsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000597 "Extend base class method: Stuff the source in the line cache first"
David Scherer7aced172000-08-15 01:13:23 +0000598 filename = self.stuffsource(source)
599 self.more = 0
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000600 self.save_warnings_filters = warnings.filters[:]
601 warnings.filterwarnings(action="error", category=SyntaxWarning)
Martin v. Löwis98ff8982007-08-13 06:03:15 +0000602 # at the moment, InteractiveInterpreter expects str
603 assert isinstance(source, str)
604 #if isinstance(source, str):
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000605 # from idlelib import IOBinding
Martin v. Löwis98ff8982007-08-13 06:03:15 +0000606 # try:
607 # source = source.encode(IOBinding.encoding)
608 # except UnicodeError:
609 # self.tkconsole.resetoutput()
610 # self.write("Unsupported characters in input\n")
611 # return
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000612 try:
Kurt B. Kaiser935ea9a2005-05-10 03:44:24 +0000613 # InteractiveInterpreter.runsource() calls its runcode() method,
614 # which is overridden (see below)
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000615 return InteractiveInterpreter.runsource(self, source, filename)
616 finally:
617 if self.save_warnings_filters is not None:
618 warnings.filters[:] = self.save_warnings_filters
619 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000620
621 def stuffsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000622 "Stuff source in the filename cache"
David Scherer7aced172000-08-15 01:13:23 +0000623 filename = "<pyshell#%d>" % self.gid
624 self.gid = self.gid + 1
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000625 lines = source.split("\n")
David Scherer7aced172000-08-15 01:13:23 +0000626 linecache.cache[filename] = len(source)+1, 0, lines, filename
627 return filename
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000628
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000629 def prepend_syspath(self, filename):
630 "Prepend sys.path with file's directory if not already included"
631 self.runcommand("""if 1:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000632 _filename = %r
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000633 import sys as _sys
634 from os.path import dirname as _dirname
635 _dir = _dirname(_filename)
636 if not _dir in _sys.path:
637 _sys.path.insert(0, _dir)
638 del _filename, _sys, _dirname, _dir
Walter Dörwald70a6b492004-02-12 17:35:32 +0000639 \n""" % (filename,))
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000640
David Scherer7aced172000-08-15 01:13:23 +0000641 def showsyntaxerror(self, filename=None):
Guido van Rossum33d26892007-08-05 15:29:28 +0000642 """Override Interactive Interpreter method: Use Colorizing
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000643
644 Color the offending position instead of printing it and pointing at it
645 with a caret.
646
647 """
Guido van Rossum33d26892007-08-05 15:29:28 +0000648 tkconsole = self.tkconsole
649 text = tkconsole.text
650 text.tag_remove("ERROR", "1.0", "end")
David Scherer7aced172000-08-15 01:13:23 +0000651 type, value, tb = sys.exc_info()
Ned Deily79746422011-09-14 14:49:14 -0700652 msg = getattr(value, 'msg', '') or value or "<no detail available>"
653 lineno = getattr(value, 'lineno', '') or 1
654 offset = getattr(value, 'offset', '') or 0
Guido van Rossum33d26892007-08-05 15:29:28 +0000655 if offset == 0:
656 lineno += 1 #mark end of offending line
657 if lineno == 1:
658 pos = "iomark + %d chars" % (offset-1)
David Scherer7aced172000-08-15 01:13:23 +0000659 else:
Guido van Rossum33d26892007-08-05 15:29:28 +0000660 pos = "iomark linestart + %d lines + %d chars" % \
661 (lineno-1, offset-1)
662 tkconsole.colorize_syntax_error(text, pos)
663 tkconsole.resetoutput()
664 self.write("SyntaxError: %s\n" % msg)
665 tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000666
667 def showtraceback(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000668 "Extend base class method to reset output properly"
David Scherer7aced172000-08-15 01:13:23 +0000669 self.tkconsole.resetoutput()
670 self.checklinecache()
671 InteractiveInterpreter.showtraceback(self)
Chui Tey5d2af632002-05-26 13:36:41 +0000672 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
673 self.tkconsole.open_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +0000674
675 def checklinecache(self):
676 c = linecache.cache
Guido van Rossum36e0a922007-07-20 04:05:57 +0000677 for key in list(c.keys()):
David Scherer7aced172000-08-15 01:13:23 +0000678 if key[:1] + key[-1:] != "<>":
679 del c[key]
680
Chui Tey5d2af632002-05-26 13:36:41 +0000681 def runcommand(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000682 "Run the code without invoking the debugger"
Chui Tey5d2af632002-05-26 13:36:41 +0000683 # The code better not raise an exception!
684 if self.tkconsole.executing:
Neal Norwitzf4c4f112002-11-30 18:49:10 +0000685 self.display_executing_dialog()
Chui Tey5d2af632002-05-26 13:36:41 +0000686 return 0
687 if self.rpcclt:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000688 self.rpcclt.remotequeue("exec", "runcode", (code,), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000689 else:
Georg Brandl7cae87c2006-09-06 06:51:57 +0000690 exec(code, self.locals)
Chui Tey5d2af632002-05-26 13:36:41 +0000691 return 1
692
David Scherer7aced172000-08-15 01:13:23 +0000693 def runcode(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000694 "Override base class method"
Chui Tey5d2af632002-05-26 13:36:41 +0000695 if self.tkconsole.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000696 self.interp.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000697 self.checklinecache()
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000698 if self.save_warnings_filters is not None:
699 warnings.filters[:] = self.save_warnings_filters
700 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000701 debugger = self.debugger
702 try:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000703 self.tkconsole.beginexecuting()
Thomas Wouterscf297e42007-02-23 15:07:44 +0000704 if not debugger and self.rpcclt is not None:
705 self.active_seq = self.rpcclt.asyncqueue("exec", "runcode",
706 (code,), {})
707 elif debugger:
708 debugger.run(code, self.locals)
709 else:
710 exec(code, self.locals)
711 except SystemExit:
712 if not self.tkconsole.closing:
713 if tkMessageBox.askyesno(
714 "Exit?",
715 "Do you want to exit altogether?",
716 default="yes",
717 master=self.tkconsole.text):
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000718 raise
Thomas Wouterscf297e42007-02-23 15:07:44 +0000719 else:
Guido van Rossum5dc0d972007-02-25 22:37:36 +0000720 self.showtraceback()
Thomas Wouterscf297e42007-02-23 15:07:44 +0000721 else:
722 raise
723 except:
724 if use_subprocess:
725 print("IDLE internal error in runcode()",
726 file=self.tkconsole.stderr)
David Scherer7aced172000-08-15 01:13:23 +0000727 self.showtraceback()
Thomas Wouterscf297e42007-02-23 15:07:44 +0000728 self.tkconsole.endexecuting()
729 else:
730 if self.tkconsole.canceled:
731 self.tkconsole.canceled = False
732 print("KeyboardInterrupt", file=self.tkconsole.stderr)
733 else:
734 self.showtraceback()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000735 finally:
736 if not use_subprocess:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000737 try:
738 self.tkconsole.endexecuting()
739 except AttributeError: # shell may have closed
740 pass
David Scherer7aced172000-08-15 01:13:23 +0000741
742 def write(self, s):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000743 "Override base class method"
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000744 self.tkconsole.stderr.write(s)
David Scherer7aced172000-08-15 01:13:23 +0000745
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000746 def display_port_binding_error(self):
747 tkMessageBox.showerror(
748 "Port Binding Error",
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000749 "IDLE can't bind to a TCP/IP port, which is necessary to "
750 "communicate with its Python execution server. This might be "
751 "because no networking is installed on this computer. "
752 "Run IDLE with the -n command line switch to start without a "
753 "subprocess and refer to Help/IDLE Help 'Running without a "
754 "subprocess' for further details.",
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000755 master=self.tkconsole.text)
756
757 def display_no_subprocess_error(self):
758 tkMessageBox.showerror(
759 "Subprocess Startup Error",
760 "IDLE's subprocess didn't make connection. Either IDLE can't "
761 "start a subprocess or personal firewall software is blocking "
762 "the connection.",
763 master=self.tkconsole.text)
764
765 def display_executing_dialog(self):
766 tkMessageBox.showerror(
767 "Already executing",
768 "The Python Shell window is already executing a command; "
769 "please wait until it is finished.",
770 master=self.tkconsole.text)
771
772
David Scherer7aced172000-08-15 01:13:23 +0000773class PyShell(OutputWindow):
774
775 shell_title = "Python Shell"
776
777 # Override classes
778 ColorDelegator = ModifiedColorDelegator
779 UndoDelegator = ModifiedUndoDelegator
780
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000781 # Override menus
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000782 menu_specs = [
783 ("file", "_File"),
784 ("edit", "_Edit"),
Kurt B. Kaiser4cc5ef52003-01-22 00:23:23 +0000785 ("debug", "_Debug"),
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000786 ("options", "_Options"),
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000787 ("windows", "_Windows"),
788 ("help", "_Help"),
789 ]
David Scherer7aced172000-08-15 01:13:23 +0000790
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000791 if macosxSupport.runningAsOSXApp():
792 del menu_specs[-3]
793 menu_specs[-2] = ("windows", "_Window")
794
795
David Scherer7aced172000-08-15 01:13:23 +0000796 # New classes
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000797 from idlelib.IdleHistory import History
David Scherer7aced172000-08-15 01:13:23 +0000798
799 def __init__(self, flist=None):
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000800 if use_subprocess:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000801 ms = self.menu_specs
802 if ms[2][0] != "shell":
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000803 ms.insert(2, ("shell", "She_ll"))
David Scherer7aced172000-08-15 01:13:23 +0000804 self.interp = ModifiedInterpreter(self)
805 if flist is None:
806 root = Tk()
807 fixwordbreaks(root)
808 root.withdraw()
809 flist = PyShellFileList(root)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000810 #
David Scherer7aced172000-08-15 01:13:23 +0000811 OutputWindow.__init__(self, flist, None, None)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000812 #
Kurt B. Kaiser6af44982005-01-19 00:22:59 +0000813## self.config(usetabs=1, indentwidth=8, context_use_ps1=1)
814 self.usetabs = True
815 # indentwidth must be 8 when using tabs. See note in EditorWindow:
816 self.indentwidth = 8
817 self.context_use_ps1 = True
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000818 #
David Scherer7aced172000-08-15 01:13:23 +0000819 text = self.text
820 text.configure(wrap="char")
821 text.bind("<<newline-and-indent>>", self.enter_callback)
822 text.bind("<<plain-newline-and-indent>>", self.linefeed_callback)
823 text.bind("<<interrupt-execution>>", self.cancel_callback)
David Scherer7aced172000-08-15 01:13:23 +0000824 text.bind("<<end-of-file>>", self.eof_callback)
825 text.bind("<<open-stack-viewer>>", self.open_stack_viewer)
Kurt B. Kaiser57bfe5d2003-05-10 00:09:52 +0000826 text.bind("<<toggle-debugger>>", self.toggle_debugger)
David Scherer7aced172000-08-15 01:13:23 +0000827 text.bind("<<toggle-jit-stack-viewer>>", self.toggle_jit_stack_viewer)
Kurt B. Kaiser8a78cad2007-12-13 03:38:16 +0000828 self.color = color = self.ColorDelegator()
829 self.per.insertfilter(color)
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000830 if use_subprocess:
831 text.bind("<<view-restart>>", self.view_restart_mark)
832 text.bind("<<restart-shell>>", self.restart_shell)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000833 #
David Scherer7aced172000-08-15 01:13:23 +0000834 self.save_stdout = sys.stdout
835 self.save_stderr = sys.stderr
836 self.save_stdin = sys.stdin
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000837 from idlelib import IOBinding
Martin v. Löwisbcc651a2003-06-22 07:52:56 +0000838 self.stdout = PseudoFile(self, "stdout", IOBinding.encoding)
839 self.stderr = PseudoFile(self, "stderr", IOBinding.encoding)
840 self.console = PseudoFile(self, "console", IOBinding.encoding)
Chui Tey5d2af632002-05-26 13:36:41 +0000841 if not use_subprocess:
842 sys.stdout = self.stdout
Kurt B. Kaiser7cec2522007-08-31 04:15:13 +0000843 sys.stderr = self.stderr
Chui Tey5d2af632002-05-26 13:36:41 +0000844 sys.stdin = self
Kurt B. Kaiserf609a342007-12-28 03:57:56 +0000845 try:
846 # page help() text to shell.
847 import pydoc # import must be done here to capture i/o rebinding.
848 # XXX KBK 27Dec07 use a textView someday, but must work w/o subproc
849 pydoc.pager = pydoc.plainpager
850 except:
851 sys.stderr = sys.__stderr__
852 raise
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000853 #
David Scherer7aced172000-08-15 01:13:23 +0000854 self.history = self.History(self.text)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000855 #
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000856 self.pollinterval = 50 # millisec
Chui Tey5d2af632002-05-26 13:36:41 +0000857
Kurt B. Kaiser4d5bc602004-06-06 01:29:22 +0000858 def get_standard_extension_names(self):
859 return idleConf.GetExtensions(shell_only=True)
860
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000861 reading = False
862 executing = False
863 canceled = False
864 endoffile = False
865 closing = False
David Scherer7aced172000-08-15 01:13:23 +0000866
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +0000867 def set_warning_stream(self, stream):
Skip Montanarod9161422004-07-06 21:53:27 +0000868 global warning_stream
869 warning_stream = stream
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +0000870
871 def get_warning_stream(self):
872 return warning_stream
873
David Scherer7aced172000-08-15 01:13:23 +0000874 def toggle_debugger(self, event=None):
875 if self.executing:
876 tkMessageBox.showerror("Don't debug now",
877 "You can only toggle the debugger when idle",
878 master=self.text)
879 self.set_debugger_indicator()
880 return "break"
881 else:
882 db = self.interp.getdebugger()
883 if db:
884 self.close_debugger()
885 else:
886 self.open_debugger()
887
888 def set_debugger_indicator(self):
889 db = self.interp.getdebugger()
890 self.setvar("<<toggle-debugger>>", not not db)
891
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000892 def toggle_jit_stack_viewer(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +0000893 pass # All we need is the variable
894
895 def close_debugger(self):
896 db = self.interp.getdebugger()
897 if db:
898 self.interp.setdebugger(None)
899 db.close()
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000900 if self.interp.rpcclt:
901 RemoteDebugger.close_remote_debugger(self.interp.rpcclt)
David Scherer7aced172000-08-15 01:13:23 +0000902 self.resetoutput()
903 self.console.write("[DEBUG OFF]\n")
904 sys.ps1 = ">>> "
905 self.showprompt()
906 self.set_debugger_indicator()
907
908 def open_debugger(self):
Chui Tey5d2af632002-05-26 13:36:41 +0000909 if self.interp.rpcclt:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000910 dbg_gui = RemoteDebugger.start_remote_debugger(self.interp.rpcclt,
911 self)
912 else:
913 dbg_gui = Debugger.Debugger(self)
914 self.interp.setdebugger(dbg_gui)
915 dbg_gui.load_breakpoints()
Chui Tey5d2af632002-05-26 13:36:41 +0000916 sys.ps1 = "[DEBUG ON]\n>>> "
917 self.showprompt()
918 self.set_debugger_indicator()
919
David Scherer7aced172000-08-15 01:13:23 +0000920 def beginexecuting(self):
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000921 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +0000922 self.resetoutput()
923 self.executing = 1
David Scherer7aced172000-08-15 01:13:23 +0000924
925 def endexecuting(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000926 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +0000927 self.executing = 0
928 self.canceled = 0
Chui Tey5d2af632002-05-26 13:36:41 +0000929 self.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000930
931 def close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000932 "Extend EditorWindow.close()"
David Scherer7aced172000-08-15 01:13:23 +0000933 if self.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000934 response = tkMessageBox.askokcancel(
David Scherer7aced172000-08-15 01:13:23 +0000935 "Kill?",
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000936 "The program is still running!\n Do you want to kill it?",
David Scherer7aced172000-08-15 01:13:23 +0000937 default="ok",
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000938 parent=self.text)
Benjamin Peterson2a691a82008-03-31 01:51:45 +0000939 if response is False:
David Scherer7aced172000-08-15 01:13:23 +0000940 return "cancel"
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +0000941 if self.reading:
942 self.top.quit()
943 self.canceled = True
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000944 self.closing = True
945 # Wait for poll_subprocess() rescheduling to stop
946 self.text.after(2 * self.pollinterval, self.close2)
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000947
948 def close2(self):
949 return EditorWindow.close(self)
David Scherer7aced172000-08-15 01:13:23 +0000950
951 def _close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000952 "Extend EditorWindow._close(), shut down debugger and execution server"
David Scherer7aced172000-08-15 01:13:23 +0000953 self.close_debugger()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000954 if use_subprocess:
955 self.interp.kill_subprocess()
David Scherer7aced172000-08-15 01:13:23 +0000956 # Restore std streams
957 sys.stdout = self.save_stdout
958 sys.stderr = self.save_stderr
959 sys.stdin = self.save_stdin
960 # Break cycles
961 self.interp = None
962 self.console = None
David Scherer7aced172000-08-15 01:13:23 +0000963 self.flist.pyshell = None
964 self.history = None
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000965 EditorWindow._close(self)
David Scherer7aced172000-08-15 01:13:23 +0000966
967 def ispythonsource(self, filename):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000968 "Override EditorWindow method: never remove the colorizer"
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000969 return True
David Scherer7aced172000-08-15 01:13:23 +0000970
971 def short_title(self):
972 return self.shell_title
973
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000974 COPYRIGHT = \
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000975 'Type "copyright", "credits" or "license()" for more information.'
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000976
David Scherer7aced172000-08-15 01:13:23 +0000977 def begin(self):
Kurt B. Kaiser7378df72007-08-11 04:20:51 +0000978 self.text.mark_set("iomark", "insert")
David Scherer7aced172000-08-15 01:13:23 +0000979 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000980 if use_subprocess:
981 nosub = ''
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000982 client = self.interp.start_subprocess()
983 if not client:
984 self.close()
Kurt B. Kaiser76637292004-01-21 22:10:01 +0000985 return False
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000986 else:
987 nosub = "==== No Subprocess ===="
Raymond Hettingera2a8e8b2009-01-27 00:28:36 +0000988 self.write("Python %s on %s\n%s\n%s" %
989 (sys.version, sys.platform, self.COPYRIGHT, nosub))
David Scherer7aced172000-08-15 01:13:23 +0000990 self.showprompt()
Georg Brandl14fc4272008-05-17 18:39:55 +0000991 import tkinter
992 tkinter._default_root = None # 03Jan04 KBK What's this?
Kurt B. Kaiser76637292004-01-21 22:10:01 +0000993 return True
David Scherer7aced172000-08-15 01:13:23 +0000994
995 def readline(self):
996 save = self.reading
997 try:
998 self.reading = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +0000999 self.top.mainloop() # nested mainloop()
David Scherer7aced172000-08-15 01:13:23 +00001000 finally:
1001 self.reading = save
1002 line = self.text.get("iomark", "end-1c")
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001003 if len(line) == 0: # may be EOF if we quit our mainloop with Ctrl-C
1004 line = "\n"
David Scherer7aced172000-08-15 01:13:23 +00001005 self.resetoutput()
1006 if self.canceled:
1007 self.canceled = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001008 if not use_subprocess:
1009 raise KeyboardInterrupt
David Scherer7aced172000-08-15 01:13:23 +00001010 if self.endoffile:
1011 self.endoffile = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001012 line = ""
David Scherer7aced172000-08-15 01:13:23 +00001013 return line
1014
1015 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001016 return True
David Scherer7aced172000-08-15 01:13:23 +00001017
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001018 def cancel_callback(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +00001019 try:
1020 if self.text.compare("sel.first", "!=", "sel.last"):
1021 return # Active selection -- always use default binding
1022 except:
1023 pass
1024 if not (self.executing or self.reading):
1025 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001026 self.interp.write("KeyboardInterrupt\n")
David Scherer7aced172000-08-15 01:13:23 +00001027 self.showprompt()
1028 return "break"
1029 self.endoffile = 0
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001030 self.canceled = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001031 if (self.executing and self.interp.rpcclt):
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +00001032 if self.interp.getdebugger():
1033 self.interp.restart_subprocess()
1034 else:
1035 self.interp.interrupt_subprocess()
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001036 if self.reading:
1037 self.top.quit() # exit the nested mainloop() in readline()
David Scherer7aced172000-08-15 01:13:23 +00001038 return "break"
1039
1040 def eof_callback(self, event):
1041 if self.executing and not self.reading:
1042 return # Let the default binding (delete next char) take over
1043 if not (self.text.compare("iomark", "==", "insert") and
1044 self.text.compare("insert", "==", "end-1c")):
1045 return # Let the default binding (delete next char) take over
1046 if not self.executing:
David Scherer7aced172000-08-15 01:13:23 +00001047 self.resetoutput()
1048 self.close()
1049 else:
1050 self.canceled = 0
1051 self.endoffile = 1
1052 self.top.quit()
1053 return "break"
1054
David Scherer7aced172000-08-15 01:13:23 +00001055 def linefeed_callback(self, event):
1056 # Insert a linefeed without entering anything (still autoindented)
1057 if self.reading:
1058 self.text.insert("insert", "\n")
1059 self.text.see("insert")
1060 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001061 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001062 return "break"
1063
1064 def enter_callback(self, event):
1065 if self.executing and not self.reading:
1066 return # Let the default binding (insert '\n') take over
1067 # If some text is selected, recall the selection
1068 # (but only if this before the I/O mark)
1069 try:
1070 sel = self.text.get("sel.first", "sel.last")
1071 if sel:
1072 if self.text.compare("sel.last", "<=", "iomark"):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001073 self.recall(sel, event)
David Scherer7aced172000-08-15 01:13:23 +00001074 return "break"
1075 except:
1076 pass
1077 # If we're strictly before the line containing iomark, recall
1078 # the current line, less a leading prompt, less leading or
1079 # trailing whitespace
1080 if self.text.compare("insert", "<", "iomark linestart"):
1081 # Check if there's a relevant stdin range -- if so, use it
1082 prev = self.text.tag_prevrange("stdin", "insert")
1083 if prev and self.text.compare("insert", "<", prev[1]):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001084 self.recall(self.text.get(prev[0], prev[1]), event)
David Scherer7aced172000-08-15 01:13:23 +00001085 return "break"
1086 next = self.text.tag_nextrange("stdin", "insert")
1087 if next and self.text.compare("insert lineend", ">=", next[0]):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001088 self.recall(self.text.get(next[0], next[1]), event)
David Scherer7aced172000-08-15 01:13:23 +00001089 return "break"
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001090 # No stdin mark -- just get the current line, less any prompt
Kurt B. Kaiserb1754452005-11-18 22:05:48 +00001091 indices = self.text.tag_nextrange("console", "insert linestart")
1092 if indices and \
1093 self.text.compare(indices[0], "<=", "insert linestart"):
1094 self.recall(self.text.get(indices[1], "insert lineend"), event)
1095 else:
1096 self.recall(self.text.get("insert linestart", "insert lineend"), event)
David Scherer7aced172000-08-15 01:13:23 +00001097 return "break"
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001098 # If we're between the beginning of the line and the iomark, i.e.
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001099 # in the prompt area, move to the end of the prompt
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001100 if self.text.compare("insert", "<", "iomark"):
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001101 self.text.mark_set("insert", "iomark")
David Scherer7aced172000-08-15 01:13:23 +00001102 # If we're in the current input and there's only whitespace
1103 # beyond the cursor, erase that whitespace first
1104 s = self.text.get("insert", "end-1c")
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001105 if s and not s.strip():
David Scherer7aced172000-08-15 01:13:23 +00001106 self.text.delete("insert", "end-1c")
1107 # If we're in the current input before its last line,
1108 # insert a newline right at the insert point
1109 if self.text.compare("insert", "<", "end-1c linestart"):
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001110 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001111 return "break"
1112 # We're in the last line; append a newline and submit it
1113 self.text.mark_set("insert", "end-1c")
1114 if self.reading:
1115 self.text.insert("insert", "\n")
1116 self.text.see("insert")
1117 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001118 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001119 self.text.tag_add("stdin", "iomark", "end-1c")
1120 self.text.update_idletasks()
1121 if self.reading:
Neal Norwitzce96f692006-03-17 06:49:51 +00001122 self.top.quit() # Break out of recursive mainloop()
David Scherer7aced172000-08-15 01:13:23 +00001123 else:
1124 self.runit()
1125 return "break"
1126
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001127 def recall(self, s, event):
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001128 # remove leading and trailing empty or whitespace lines
1129 s = re.sub(r'^\s*\n', '' , s)
1130 s = re.sub(r'\n\s*$', '', s)
1131 lines = s.split('\n')
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001132 self.text.undo_block_start()
1133 try:
1134 self.text.tag_remove("sel", "1.0", "end")
1135 self.text.mark_set("insert", "end-1c")
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001136 prefix = self.text.get("insert linestart", "insert")
1137 if prefix.rstrip().endswith(':'):
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001138 self.newline_and_indent_event(event)
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001139 prefix = self.text.get("insert linestart", "insert")
1140 self.text.insert("insert", lines[0].strip())
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001141 if len(lines) > 1:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001142 orig_base_indent = re.search(r'^([ \t]*)', lines[0]).group(0)
1143 new_base_indent = re.search(r'^([ \t]*)', prefix).group(0)
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001144 for line in lines[1:]:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001145 if line.startswith(orig_base_indent):
1146 # replace orig base indentation with new indentation
1147 line = new_base_indent + line[len(orig_base_indent):]
1148 self.text.insert('insert', '\n'+line.rstrip())
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001149 finally:
1150 self.text.see("insert")
1151 self.text.undo_block_stop()
David Scherer7aced172000-08-15 01:13:23 +00001152
1153 def runit(self):
1154 line = self.text.get("iomark", "end-1c")
1155 # Strip off last newline and surrounding whitespace.
1156 # (To allow you to hit return twice to end a statement.)
1157 i = len(line)
1158 while i > 0 and line[i-1] in " \t":
1159 i = i-1
1160 if i > 0 and line[i-1] == "\n":
1161 i = i-1
1162 while i > 0 and line[i-1] in " \t":
1163 i = i-1
1164 line = line[:i]
1165 more = self.interp.runsource(line)
David Scherer7aced172000-08-15 01:13:23 +00001166
David Scherer7aced172000-08-15 01:13:23 +00001167 def open_stack_viewer(self, event=None):
Chui Tey5d2af632002-05-26 13:36:41 +00001168 if self.interp.rpcclt:
1169 return self.interp.remote_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +00001170 try:
1171 sys.last_traceback
1172 except:
1173 tkMessageBox.showerror("No stack trace",
1174 "There is no stack trace yet.\n"
1175 "(sys.last_traceback is not defined)",
1176 master=self.text)
1177 return
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +00001178 from idlelib.StackViewer import StackBrowser
David Scherer7aced172000-08-15 01:13:23 +00001179 sv = StackBrowser(self.root, self.flist)
1180
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001181 def view_restart_mark(self, event=None):
1182 self.text.see("iomark")
1183 self.text.see("restart")
1184
1185 def restart_shell(self, event=None):
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +00001186 self.interp.restart_subprocess()
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001187
David Scherer7aced172000-08-15 01:13:23 +00001188 def showprompt(self):
1189 self.resetoutput()
1190 try:
1191 s = str(sys.ps1)
1192 except:
1193 s = ""
1194 self.console.write(s)
1195 self.text.mark_set("insert", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001196 self.set_line_and_column()
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +00001197 self.io.reset_undo()
David Scherer7aced172000-08-15 01:13:23 +00001198
1199 def resetoutput(self):
1200 source = self.text.get("iomark", "end-1c")
1201 if self.history:
1202 self.history.history_store(source)
1203 if self.text.get("end-2c") != "\n":
1204 self.text.insert("end-1c", "\n")
1205 self.text.mark_set("iomark", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001206 self.set_line_and_column()
David Scherer7aced172000-08-15 01:13:23 +00001207
1208 def write(self, s, tags=()):
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001209 try:
1210 self.text.mark_gravity("iomark", "right")
1211 OutputWindow.write(self, s, tags, "iomark")
1212 self.text.mark_gravity("iomark", "left")
1213 except:
Kurt B. Kaisercbbe98f2007-08-12 01:52:35 +00001214 raise ###pass # ### 11Aug07 KBK if we are expecting exceptions
1215 # let's find out what they are and be specific.
David Scherer7aced172000-08-15 01:13:23 +00001216 if self.canceled:
1217 self.canceled = 0
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001218 if not use_subprocess:
1219 raise KeyboardInterrupt
David Scherer7aced172000-08-15 01:13:23 +00001220
Kurt B. Kaiserdcba6622004-12-21 22:10:32 +00001221class PseudoFile(object):
David Scherer7aced172000-08-15 01:13:23 +00001222
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001223 def __init__(self, shell, tags, encoding=None):
David Scherer7aced172000-08-15 01:13:23 +00001224 self.shell = shell
1225 self.tags = tags
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001226 self.encoding = encoding
David Scherer7aced172000-08-15 01:13:23 +00001227
1228 def write(self, s):
1229 self.shell.write(s, self.tags)
1230
Kurt B. Kaiser66aaf742007-08-09 18:00:23 +00001231 def writelines(self, lines):
1232 for line in lines:
1233 self.write(line)
David Scherer7aced172000-08-15 01:13:23 +00001234
1235 def flush(self):
1236 pass
1237
1238 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001239 return True
David Scherer7aced172000-08-15 01:13:23 +00001240
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001241
David Scherer7aced172000-08-15 01:13:23 +00001242usage_msg = """\
David Scherer7aced172000-08-15 01:13:23 +00001243
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001244USAGE: idle [-deins] [-t title] [file]*
1245 idle [-dns] [-t title] (-c cmd | -r file) [arg]*
1246 idle [-dns] [-t title] - [arg]*
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001247
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001248 -h print this help message and exit
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001249 -n run IDLE without a subprocess (see Help/IDLE Help for details)
David Scherer7aced172000-08-15 01:13:23 +00001250
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001251The following options will override the IDLE 'settings' configuration:
Kurt B. Kaiser96d88422001-07-17 04:59:01 +00001252
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001253 -e open an edit window
1254 -i open a shell window
1255
1256The following options imply -i and will open a shell:
1257
1258 -c cmd run the command in a shell, or
1259 -r file run script from file
1260
1261 -d enable the debugger
1262 -s run $IDLESTARTUP or $PYTHONSTARTUP before anything else
1263 -t title set title of shell window
1264
1265A default edit window will be bypassed when -c, -r, or - are used.
1266
1267[arg]* are passed to the command (-c) or script (-r) in sys.argv[1:].
1268
1269Examples:
1270
1271idle
1272 Open an edit window or shell depending on IDLE's configuration.
1273
1274idle foo.py foobar.py
1275 Edit the files, also open a shell if configured to start with shell.
1276
1277idle -est "Baz" foo.py
1278 Run $IDLESTARTUP or $PYTHONSTARTUP, edit foo.py, and open a shell
1279 window with the title "Baz".
1280
Neal Norwitz752abd02008-05-13 04:55:24 +00001281idle -c "import sys; print(sys.argv)" "foo"
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001282 Open a shell window and run the command, passing "-c" in sys.argv[0]
1283 and "foo" in sys.argv[1].
1284
1285idle -d -s -r foo.py "Hello World"
1286 Open a shell window, run a startup script, enable the debugger, and
1287 run foo.py, passing "foo.py" in sys.argv[0] and "Hello World" in
1288 sys.argv[1].
1289
Neal Norwitz752abd02008-05-13 04:55:24 +00001290echo "import sys; print(sys.argv)" | idle - "foobar"
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001291 Open a shell window, run the script piped in, passing '' in sys.argv[0]
1292 and "foobar" in sys.argv[1].
David Scherer7aced172000-08-15 01:13:23 +00001293"""
1294
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001295def main():
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001296 global flist, root, use_subprocess
David Scherer7aced172000-08-15 01:13:23 +00001297
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001298 use_subprocess = True
Kurt B. Kaisere866c812009-04-04 21:07:39 +00001299 enable_shell = True
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001300 enable_edit = False
1301 debug = False
1302 cmd = None
1303 script = None
1304 startup = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001305 try:
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001306 opts, args = getopt.getopt(sys.argv[1:], "c:deihnr:st:")
Guido van Rossumb940e112007-01-10 16:19:56 +00001307 except getopt.error as msg:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001308 sys.stderr.write("Error: %s\n" % str(msg))
1309 sys.stderr.write(usage_msg)
1310 sys.exit(2)
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001311 for o, a in opts:
1312 if o == '-c':
1313 cmd = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001314 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001315 if o == '-d':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001316 debug = True
1317 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001318 if o == '-e':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001319 enable_edit = True
Kurt B. Kaisere866c812009-04-04 21:07:39 +00001320 enable_shell = False
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001321 if o == '-h':
1322 sys.stdout.write(usage_msg)
1323 sys.exit()
1324 if o == '-i':
1325 enable_shell = True
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001326 if o == '-n':
1327 use_subprocess = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001328 if o == '-r':
1329 script = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001330 if os.path.isfile(script):
1331 pass
1332 else:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001333 print("No script file: ", script)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001334 sys.exit()
1335 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001336 if o == '-s':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001337 startup = True
1338 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001339 if o == '-t':
1340 PyShell.shell_title = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001341 enable_shell = True
1342 if args and args[0] == '-':
1343 cmd = sys.stdin.read()
1344 enable_shell = True
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001345 # process sys.argv and sys.path:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001346 for i in range(len(sys.path)):
1347 sys.path[i] = os.path.abspath(sys.path[i])
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001348 if args and args[0] == '-':
1349 sys.argv = [''] + args[1:]
1350 elif cmd:
1351 sys.argv = ['-c'] + args
1352 elif script:
1353 sys.argv = [script] + args
1354 elif args:
1355 enable_edit = True
1356 pathx = []
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001357 for filename in args:
1358 pathx.append(os.path.dirname(filename))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001359 for dir in pathx:
1360 dir = os.path.abspath(dir)
1361 if not dir in sys.path:
1362 sys.path.insert(0, dir)
Kurt B. Kaiserff002b92002-12-21 21:39:11 +00001363 else:
Neal Norwitzd082b6e2007-08-26 23:37:53 +00001364 dir = os.getcwd()
1365 if dir not in sys.path:
Kurt B. Kaiserff002b92002-12-21 21:39:11 +00001366 sys.path.insert(0, dir)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001367 # check the IDLE settings configuration (but command line overrides)
1368 edit_start = idleConf.GetOption('main', 'General',
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001369 'editor-on-startup', type='bool')
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001370 enable_edit = enable_edit or edit_start
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001371 # start editor and/or shell windows:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001372 root = Tk(className="Idle")
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001373
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001374 fixwordbreaks(root)
1375 root.withdraw()
1376 flist = PyShellFileList(root)
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001377 macosxSupport.setupApp(root, flist)
1378
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001379 if enable_edit:
1380 if not (cmd or script):
1381 for filename in args:
1382 flist.open(filename)
1383 if not args:
1384 flist.new()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001385 if enable_shell:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001386 shell = flist.open_shell()
1387 if not shell:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001388 return # couldn't open shell
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001389
1390 if macosxSupport.runningAsOSXApp() and flist.dict:
1391 # On OSX: when the user has double-clicked on a file that causes
1392 # IDLE to be launched the shell window will open just in front of
1393 # the file she wants to see. Lower the interpreter window when
1394 # there are open files.
1395 shell.top.lower()
1396
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001397 shell = flist.pyshell
1398 # handle remaining options:
1399 if debug:
1400 shell.open_debugger()
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001401 if startup:
1402 filename = os.environ.get("IDLESTARTUP") or \
1403 os.environ.get("PYTHONSTARTUP")
1404 if filename and os.path.isfile(filename):
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001405 shell.interp.execfile(filename)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001406 if shell and cmd or script:
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001407 shell.interp.runcommand("""if 1:
1408 import sys as _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001409 _sys.argv = %r
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001410 del _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001411 \n""" % (sys.argv,))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001412 if cmd:
1413 shell.interp.execsource(cmd)
1414 elif script:
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001415 shell.interp.prepend_syspath(script)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001416 shell.interp.execfile(script)
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001417
Ned Deily4ce92b22011-01-15 04:37:12 +00001418 # Check for problematic OS X Tk versions and print a warning message
1419 # in the IDLE shell window; this is less intrusive than always opening
1420 # a separate window.
1421 tkversionwarning = macosxSupport.tkVersionWarning(root)
1422 if tkversionwarning:
1423 shell.interp.runcommand(''.join(("print('", tkversionwarning, "')")))
1424
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001425 root.mainloop()
1426 root.destroy()
1427
David Scherer7aced172000-08-15 01:13:23 +00001428if __name__ == "__main__":
Kurt B. Kaiser9e8b8282003-06-15 17:38:45 +00001429 sys.modules['PyShell'] = sys.modules['__main__']
David Scherer7aced172000-08-15 01:13:23 +00001430 main()