blob: 6bf0a8c65df9c1f5a43c05532a5a522a60d0eeb8 [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 = []
Ned Deilyf505b742011-12-14 14:58:24 -0800209 try:
210 with open(self.breakpointPath, "w") as new_file:
211 for line in lines:
212 if not line.startswith(filename + '='):
213 new_file.write(line)
214 self.update_breakpoints()
215 breaks = self.breakpoints
216 if breaks:
217 new_file.write(filename + '=' + str(breaks) + '\n')
218 except IOError as err:
219 if not getattr(self.root, "breakpoint_error_displayed", False):
220 self.root.breakpoint_error_displayed = True
221 tkMessageBox.showerror(title='IDLE Error',
222 message='Unable to update breakpoint list:\n%s'
223 % str(err),
224 parent=self.text)
Chui Teya2adb0f2002-11-04 22:14:54 +0000225
226 def restore_file_breaks(self):
227 self.text.update() # this enables setting "BREAK" tags to be visible
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000228 filename = self.io.filename
229 if filename is None:
230 return
Chui Tey69371d62002-11-04 23:39:45 +0000231 if os.path.isfile(self.breakpointPath):
Victor Stinner85c67722011-09-02 00:57:04 +0200232 with open(self.breakpointPath, "r") as fp:
233 lines = fp.readlines()
Chui Tey69371d62002-11-04 23:39:45 +0000234 for line in lines:
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000235 if line.startswith(filename + '='):
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000236 breakpoint_linenumbers = eval(line[len(filename)+1:])
Chui Tey69371d62002-11-04 23:39:45 +0000237 for breakpoint_linenumber in breakpoint_linenumbers:
238 self.set_breakpoint(breakpoint_linenumber)
Chui Teya2adb0f2002-11-04 22:14:54 +0000239
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000240 def update_breakpoints(self):
241 "Retrieves all the breakpoints in the current window"
Chui Teya2adb0f2002-11-04 22:14:54 +0000242 text = self.text
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000243 ranges = text.tag_ranges("BREAK")
244 linenumber_list = self.ranges_to_linenumbers(ranges)
245 self.breakpoints = linenumber_list
246
247 def ranges_to_linenumbers(self, ranges):
248 lines = []
249 for index in range(0, len(ranges), 2):
250 lineno = int(float(ranges[index]))
251 end = int(float(ranges[index+1]))
252 while lineno < end:
253 lines.append(lineno)
254 lineno += 1
255 return lines
256
Kurt B. Kaiser11220fa2002-12-24 00:57:22 +0000257# XXX 13 Dec 2002 KBK Not used currently
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000258# def saved_change_hook(self):
259# "Extend base method - clear breaks if module is modified"
260# if not self.get_saved():
261# self.clear_file_breaks()
262# EditorWindow.saved_change_hook(self)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000263
264 def _close(self):
265 "Extend base method - clear breaks when module is closed"
266 self.clear_file_breaks()
267 EditorWindow._close(self)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000268
David Scherer7aced172000-08-15 01:13:23 +0000269
270class PyShellFileList(FileList):
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000271 "Extend base class: IDLE supports a shell and breakpoints"
David Scherer7aced172000-08-15 01:13:23 +0000272
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000273 # override FileList's class variable, instances return PyShellEditorWindow
274 # instead of EditorWindow when new edit windows are created.
David Scherer7aced172000-08-15 01:13:23 +0000275 EditorWindow = PyShellEditorWindow
276
277 pyshell = None
278
279 def open_shell(self, event=None):
280 if self.pyshell:
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000281 self.pyshell.top.wakeup()
David Scherer7aced172000-08-15 01:13:23 +0000282 else:
283 self.pyshell = PyShell(self)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000284 if self.pyshell:
285 if not self.pyshell.begin():
286 return None
David Scherer7aced172000-08-15 01:13:23 +0000287 return self.pyshell
288
289
290class ModifiedColorDelegator(ColorDelegator):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000291 "Extend base class: colorizer for the shell window itself"
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000292
Steven M. Gavab77d3432002-03-02 07:16:21 +0000293 def __init__(self):
294 ColorDelegator.__init__(self)
295 self.LoadTagDefs()
David Scherer7aced172000-08-15 01:13:23 +0000296
297 def recolorize_main(self):
298 self.tag_remove("TODO", "1.0", "iomark")
299 self.tag_add("SYNC", "1.0", "iomark")
300 ColorDelegator.recolorize_main(self)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000301
Steven M. Gavab77d3432002-03-02 07:16:21 +0000302 def LoadTagDefs(self):
303 ColorDelegator.LoadTagDefs(self)
304 theme = idleConf.GetOption('main','Theme','name')
305 self.tagdefs.update({
306 "stdin": {'background':None,'foreground':None},
307 "stdout": idleConf.GetHighlight(theme, "stdout"),
308 "stderr": idleConf.GetHighlight(theme, "stderr"),
309 "console": idleConf.GetHighlight(theme, "console"),
Steven M. Gavab77d3432002-03-02 07:16:21 +0000310 })
David Scherer7aced172000-08-15 01:13:23 +0000311
David Scherer7aced172000-08-15 01:13:23 +0000312class ModifiedUndoDelegator(UndoDelegator):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000313 "Extend base class: forbid insert/delete before the I/O mark"
David Scherer7aced172000-08-15 01:13:23 +0000314
315 def insert(self, index, chars, tags=None):
316 try:
317 if self.delegate.compare(index, "<", "iomark"):
318 self.delegate.bell()
319 return
320 except TclError:
321 pass
322 UndoDelegator.insert(self, index, chars, tags)
323
324 def delete(self, index1, index2=None):
325 try:
326 if self.delegate.compare(index1, "<", "iomark"):
327 self.delegate.bell()
328 return
329 except TclError:
330 pass
331 UndoDelegator.delete(self, index1, index2)
332
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000333
334class MyRPCClient(rpc.RPCClient):
335
336 def handle_EOF(self):
337 "Override the base class - just re-raise EOFError"
338 raise EOFError
339
Kurt B. Kaiser8d1f11b2003-05-26 22:20:34 +0000340
David Scherer7aced172000-08-15 01:13:23 +0000341class ModifiedInterpreter(InteractiveInterpreter):
342
343 def __init__(self, tkconsole):
344 self.tkconsole = tkconsole
345 locals = sys.modules['__main__'].__dict__
346 InteractiveInterpreter.__init__(self, locals=locals)
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000347 self.save_warnings_filters = None
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000348 self.restarting = False
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000349 self.subprocess_arglist = None
350 self.port = PORT
Ned Deily7aff4512011-10-30 20:01:35 -0700351 self.original_compiler_flags = self.compile.compiler.flags
David Scherer7aced172000-08-15 01:13:23 +0000352
Chui Tey5d2af632002-05-26 13:36:41 +0000353 rpcclt = None
Ned Deilye5cad232011-08-02 18:47:13 -0700354 rpcsubproc = None
Chui Tey5d2af632002-05-26 13:36:41 +0000355
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000356 def spawn_subprocess(self):
Florent Xiclunafd1b0932010-03-28 00:25:02 +0000357 if self.subprocess_arglist is None:
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000358 self.subprocess_arglist = self.build_subprocess_arglist()
Ned Deilye5cad232011-08-02 18:47:13 -0700359 self.rpcsubproc = subprocess.Popen(self.subprocess_arglist)
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000360
Tony Lowndsf53dec22002-12-20 04:24:43 +0000361 def build_subprocess_arglist(self):
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000362 assert (self.port!=0), (
363 "Socket should have been assigned a port number.")
Tony Lownds2398d572003-05-13 15:28:21 +0000364 w = ['-W' + s for s in sys.warnoptions]
365 # Maybe IDLE is installed and is being accessed via sys.path,
366 # or maybe it's not installed and the idle.py script is being
367 # run from the IDLE source directory.
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000368 del_exitf = idleConf.GetOption('main', 'General', 'delete-exitfunc',
369 default=False, type='bool')
Tony Lownds2398d572003-05-13 15:28:21 +0000370 if __name__ == 'idlelib.PyShell':
Walter Dörwald70a6b492004-02-12 17:35:32 +0000371 command = "__import__('idlelib.run').run.main(%r)" % (del_exitf,)
Tony Lowndsf2324b92002-09-29 00:34:10 +0000372 else:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000373 command = "__import__('run').main(%r)" % (del_exitf,)
Ned Deilye5cad232011-08-02 18:47:13 -0700374 return [sys.executable] + w + ["-c", command, str(self.port)]
Tony Lowndsf2324b92002-09-29 00:34:10 +0000375
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000376 def start_subprocess(self):
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000377 addr = (HOST, self.port)
378 # GUI makes several attempts to acquire socket, listens for connection
Kurt B. Kaiser5db48432003-05-15 03:40:51 +0000379 for i in range(3):
Chui Tey5d2af632002-05-26 13:36:41 +0000380 time.sleep(i)
381 try:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000382 self.rpcclt = MyRPCClient(addr)
Chui Tey5d2af632002-05-26 13:36:41 +0000383 break
Guido van Rossumb940e112007-01-10 16:19:56 +0000384 except socket.error as err:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000385 pass
Chui Tey5d2af632002-05-26 13:36:41 +0000386 else:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000387 self.display_port_binding_error()
388 return None
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000389 # if PORT was 0, system will assign an 'ephemeral' port. Find it out:
390 self.port = self.rpcclt.listening_sock.getsockname()[1]
391 # if PORT was not 0, probably working with a remote execution server
392 if PORT != 0:
393 # To allow reconnection within the 2MSL wait (cf. Stevens TCP
394 # V1, 18.6), set SO_REUSEADDR. Note that this can be problematic
395 # on Windows since the implementation allows two active sockets on
396 # the same address!
397 self.rpcclt.listening_sock.setsockopt(socket.SOL_SOCKET,
398 socket.SO_REUSEADDR, 1)
399 self.spawn_subprocess()
400 #time.sleep(20) # test to simulate GUI not accepting connection
Kurt B. Kaiserb4179362002-07-26 00:06:42 +0000401 # Accept the connection from the Python execution server
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000402 self.rpcclt.listening_sock.settimeout(10)
403 try:
404 self.rpcclt.accept()
Guido van Rossumb940e112007-01-10 16:19:56 +0000405 except socket.timeout as err:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000406 self.display_no_subprocess_error()
407 return None
Kurt B. Kaiser969de452002-06-12 03:28:57 +0000408 self.rpcclt.register("stdin", self.tkconsole)
409 self.rpcclt.register("stdout", self.tkconsole.stdout)
410 self.rpcclt.register("stderr", self.tkconsole.stderr)
Chui Tey5d2af632002-05-26 13:36:41 +0000411 self.rpcclt.register("flist", self.tkconsole.flist)
Kurt B. Kaiser8cd0def2003-01-31 05:06:43 +0000412 self.rpcclt.register("linecache", linecache)
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000413 self.rpcclt.register("interp", self)
Terry Jan Reedyda4c4672012-01-31 02:26:32 -0500414 self.transfer_path(with_cwd=True)
Chui Tey5d2af632002-05-26 13:36:41 +0000415 self.poll_subprocess()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000416 return self.rpcclt
Chui Tey5d2af632002-05-26 13:36:41 +0000417
Terry Jan Reedyda4c4672012-01-31 02:26:32 -0500418 def restart_subprocess(self, with_cwd=False):
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000419 if self.restarting:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000420 return self.rpcclt
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000421 self.restarting = True
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000422 # close only the subprocess debugger
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000423 debug = self.getdebugger()
424 if debug:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000425 try:
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000426 # Only close subprocess debugger, don't unregister gui_adap!
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000427 RemoteDebugger.close_subprocess_debugger(self.rpcclt)
428 except:
429 pass
430 # Kill subprocess, spawn a new one, accept connection.
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000431 self.rpcclt.close()
Ned Deilye5cad232011-08-02 18:47:13 -0700432 self.terminate_subprocess()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000433 console = self.tkconsole
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000434 was_executing = console.executing
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000435 console.executing = False
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000436 self.spawn_subprocess()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000437 try:
438 self.rpcclt.accept()
Guido van Rossumb940e112007-01-10 16:19:56 +0000439 except socket.timeout as err:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000440 self.display_no_subprocess_error()
441 return None
Terry Jan Reedyda4c4672012-01-31 02:26:32 -0500442 self.transfer_path(with_cwd=with_cwd)
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000443 # annotate restart in shell window and mark it
Kurt B. Kaiser4cc5ef52003-01-22 00:23:23 +0000444 console.text.delete("iomark", "end-1c")
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000445 if was_executing:
446 console.write('\n')
447 console.showprompt()
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000448 halfbar = ((int(console.width) - 16) // 2) * '='
449 console.write(halfbar + ' RESTART ' + halfbar)
450 console.text.mark_set("restart", "end-1c")
451 console.text.mark_gravity("restart", "left")
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000452 console.showprompt()
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000453 # restart subprocess debugger
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000454 if debug:
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000455 # Restarted debugger connects to current instance of debug GUI
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000456 gui = RemoteDebugger.restart_subprocess_debugger(self.rpcclt)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000457 # reload remote debugger breakpoints for all PyShellEditWindows
458 debug.load_breakpoints()
Ned Deily7aff4512011-10-30 20:01:35 -0700459 self.compile.compiler.flags = self.original_compiler_flags
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000460 self.restarting = False
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000461 return self.rpcclt
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000462
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000463 def __request_interrupt(self):
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000464 self.rpcclt.remotecall("exec", "interrupt_the_server", (), {})
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000465
466 def interrupt_subprocess(self):
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000467 threading.Thread(target=self.__request_interrupt).start()
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000468
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000469 def kill_subprocess(self):
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000470 try:
471 self.rpcclt.close()
472 except AttributeError: # no socket
473 pass
Ned Deilye5cad232011-08-02 18:47:13 -0700474 self.terminate_subprocess()
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000475 self.tkconsole.executing = False
476 self.rpcclt = None
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000477
Ned Deilye5cad232011-08-02 18:47:13 -0700478 def terminate_subprocess(self):
479 "Make sure subprocess is terminated"
480 try:
481 self.rpcsubproc.kill()
482 except OSError:
483 # process already terminated
484 return
485 else:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000486 try:
Ned Deilye5cad232011-08-02 18:47:13 -0700487 self.rpcsubproc.wait()
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000488 except OSError:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000489 return
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000490
Terry Jan Reedyda4c4672012-01-31 02:26:32 -0500491 def transfer_path(self, with_cwd=False):
492 if with_cwd: # Issue 13506
493 path = [''] # include Current Working Directory
494 path.extend(sys.path)
495 else:
496 path = sys.path
Terry Jan Reedy4d82ade2012-01-31 02:57:29 -0500497
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000498 self.runcommand("""if 1:
499 import sys as _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +0000500 _sys.path = %r
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000501 del _sys
Terry Jan Reedyda4c4672012-01-31 02:26:32 -0500502 \n""" % (path,))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000503
Chui Tey5d2af632002-05-26 13:36:41 +0000504 active_seq = None
505
506 def poll_subprocess(self):
507 clt = self.rpcclt
508 if clt is None:
509 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000510 try:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000511 response = clt.pollresponse(self.active_seq, wait=0.05)
512 except (EOFError, IOError, KeyboardInterrupt):
513 # lost connection or subprocess terminated itself, restart
514 # [the KBI is from rpc.SocketIO.handle_EOF()]
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000515 if self.tkconsole.closing:
516 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000517 response = None
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000518 self.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000519 if response:
520 self.tkconsole.resetoutput()
521 self.active_seq = None
522 how, what = response
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000523 console = self.tkconsole.console
Chui Tey5d2af632002-05-26 13:36:41 +0000524 if how == "OK":
525 if what is not None:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000526 print(repr(what), file=console)
Chui Tey5d2af632002-05-26 13:36:41 +0000527 elif how == "EXCEPTION":
Chui Tey5d2af632002-05-26 13:36:41 +0000528 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
529 self.remote_stack_viewer()
530 elif how == "ERROR":
Kurt B. Kaiser0930c432002-12-06 21:45:24 +0000531 errmsg = "PyShell.ModifiedInterpreter: Subprocess ERROR:\n"
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000532 print(errmsg, what, file=sys.__stderr__)
533 print(errmsg, what, file=console)
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000534 # we received a response to the currently active seq number:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000535 try:
536 self.tkconsole.endexecuting()
537 except AttributeError: # shell may have closed
538 pass
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000539 # Reschedule myself
540 if not self.tkconsole.closing:
541 self.tkconsole.text.after(self.tkconsole.pollinterval,
542 self.poll_subprocess)
Chui Tey5d2af632002-05-26 13:36:41 +0000543
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000544 debugger = None
545
546 def setdebugger(self, debugger):
547 self.debugger = debugger
548
549 def getdebugger(self):
550 return self.debugger
551
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000552 def open_remote_stack_viewer(self):
553 """Initiate the remote stack viewer from a separate thread.
554
555 This method is called from the subprocess, and by returning from this
556 method we allow the subprocess to unblock. After a bit the shell
557 requests the subprocess to open the remote stack viewer which returns a
Ezio Melotti60861182010-07-23 16:48:22 +0000558 static object looking at the last exception. It is queried through
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000559 the RPC mechanism.
560
561 """
562 self.tkconsole.text.after(300, self.remote_stack_viewer)
563 return
564
Chui Tey5d2af632002-05-26 13:36:41 +0000565 def remote_stack_viewer(self):
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000566 from idlelib import RemoteObjectBrowser
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000567 oid = self.rpcclt.remotequeue("exec", "stackviewer", ("flist",), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000568 if oid is None:
569 self.tkconsole.root.bell()
570 return
571 item = RemoteObjectBrowser.StubObjectTreeItem(self.rpcclt, oid)
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000572 from idlelib.TreeWidget import ScrolledCanvas, TreeNode
Chui Tey5d2af632002-05-26 13:36:41 +0000573 top = Toplevel(self.tkconsole.root)
Kurt B. Kaiser73360a32004-03-08 18:15:31 +0000574 theme = idleConf.GetOption('main','Theme','name')
575 background = idleConf.GetHighlight(theme, 'normal')['background']
576 sc = ScrolledCanvas(top, bg=background, highlightthickness=0)
Chui Tey5d2af632002-05-26 13:36:41 +0000577 sc.frame.pack(expand=1, fill="both")
578 node = TreeNode(sc.canvas, None, item)
579 node.expand()
580 # XXX Should GC the remote tree when closing the window
581
David Scherer7aced172000-08-15 01:13:23 +0000582 gid = 0
583
584 def execsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000585 "Like runsource() but assumes complete exec source"
David Scherer7aced172000-08-15 01:13:23 +0000586 filename = self.stuffsource(source)
587 self.execfile(filename, source)
588
589 def execfile(self, filename, source=None):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000590 "Execute an existing file"
David Scherer7aced172000-08-15 01:13:23 +0000591 if source is None:
Victor Stinner979482a2011-09-02 01:00:40 +0200592 with tokenize.open(filename) as fp:
Victor Stinner85c67722011-09-02 00:57:04 +0200593 source = fp.read()
David Scherer7aced172000-08-15 01:13:23 +0000594 try:
595 code = compile(source, filename, "exec")
596 except (OverflowError, SyntaxError):
597 self.tkconsole.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000598 tkerr = self.tkconsole.stderr
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000599 print('*** Error in script or command!\n', file=tkerr)
600 print('Traceback (most recent call last):', file=tkerr)
David Scherer7aced172000-08-15 01:13:23 +0000601 InteractiveInterpreter.showsyntaxerror(self, filename)
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000602 self.tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000603 else:
604 self.runcode(code)
605
606 def runsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000607 "Extend base class method: Stuff the source in the line cache first"
David Scherer7aced172000-08-15 01:13:23 +0000608 filename = self.stuffsource(source)
609 self.more = 0
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000610 self.save_warnings_filters = warnings.filters[:]
611 warnings.filterwarnings(action="error", category=SyntaxWarning)
Martin v. Löwis98ff8982007-08-13 06:03:15 +0000612 # at the moment, InteractiveInterpreter expects str
613 assert isinstance(source, str)
614 #if isinstance(source, str):
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000615 # from idlelib import IOBinding
Martin v. Löwis98ff8982007-08-13 06:03:15 +0000616 # try:
617 # source = source.encode(IOBinding.encoding)
618 # except UnicodeError:
619 # self.tkconsole.resetoutput()
620 # self.write("Unsupported characters in input\n")
621 # return
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000622 try:
Kurt B. Kaiser935ea9a2005-05-10 03:44:24 +0000623 # InteractiveInterpreter.runsource() calls its runcode() method,
624 # which is overridden (see below)
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000625 return InteractiveInterpreter.runsource(self, source, filename)
626 finally:
627 if self.save_warnings_filters is not None:
628 warnings.filters[:] = self.save_warnings_filters
629 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000630
631 def stuffsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000632 "Stuff source in the filename cache"
David Scherer7aced172000-08-15 01:13:23 +0000633 filename = "<pyshell#%d>" % self.gid
634 self.gid = self.gid + 1
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000635 lines = source.split("\n")
David Scherer7aced172000-08-15 01:13:23 +0000636 linecache.cache[filename] = len(source)+1, 0, lines, filename
637 return filename
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000638
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000639 def prepend_syspath(self, filename):
640 "Prepend sys.path with file's directory if not already included"
641 self.runcommand("""if 1:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000642 _filename = %r
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000643 import sys as _sys
644 from os.path import dirname as _dirname
645 _dir = _dirname(_filename)
646 if not _dir in _sys.path:
647 _sys.path.insert(0, _dir)
648 del _filename, _sys, _dirname, _dir
Walter Dörwald70a6b492004-02-12 17:35:32 +0000649 \n""" % (filename,))
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000650
David Scherer7aced172000-08-15 01:13:23 +0000651 def showsyntaxerror(self, filename=None):
Guido van Rossum33d26892007-08-05 15:29:28 +0000652 """Override Interactive Interpreter method: Use Colorizing
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000653
654 Color the offending position instead of printing it and pointing at it
655 with a caret.
656
657 """
Guido van Rossum33d26892007-08-05 15:29:28 +0000658 tkconsole = self.tkconsole
659 text = tkconsole.text
660 text.tag_remove("ERROR", "1.0", "end")
David Scherer7aced172000-08-15 01:13:23 +0000661 type, value, tb = sys.exc_info()
Ned Deily79746422011-09-14 14:49:14 -0700662 msg = getattr(value, 'msg', '') or value or "<no detail available>"
663 lineno = getattr(value, 'lineno', '') or 1
664 offset = getattr(value, 'offset', '') or 0
Guido van Rossum33d26892007-08-05 15:29:28 +0000665 if offset == 0:
666 lineno += 1 #mark end of offending line
667 if lineno == 1:
668 pos = "iomark + %d chars" % (offset-1)
David Scherer7aced172000-08-15 01:13:23 +0000669 else:
Guido van Rossum33d26892007-08-05 15:29:28 +0000670 pos = "iomark linestart + %d lines + %d chars" % \
671 (lineno-1, offset-1)
672 tkconsole.colorize_syntax_error(text, pos)
673 tkconsole.resetoutput()
674 self.write("SyntaxError: %s\n" % msg)
675 tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000676
677 def showtraceback(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000678 "Extend base class method to reset output properly"
David Scherer7aced172000-08-15 01:13:23 +0000679 self.tkconsole.resetoutput()
680 self.checklinecache()
681 InteractiveInterpreter.showtraceback(self)
Chui Tey5d2af632002-05-26 13:36:41 +0000682 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
683 self.tkconsole.open_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +0000684
685 def checklinecache(self):
686 c = linecache.cache
Guido van Rossum36e0a922007-07-20 04:05:57 +0000687 for key in list(c.keys()):
David Scherer7aced172000-08-15 01:13:23 +0000688 if key[:1] + key[-1:] != "<>":
689 del c[key]
690
Chui Tey5d2af632002-05-26 13:36:41 +0000691 def runcommand(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000692 "Run the code without invoking the debugger"
Chui Tey5d2af632002-05-26 13:36:41 +0000693 # The code better not raise an exception!
694 if self.tkconsole.executing:
Neal Norwitzf4c4f112002-11-30 18:49:10 +0000695 self.display_executing_dialog()
Chui Tey5d2af632002-05-26 13:36:41 +0000696 return 0
697 if self.rpcclt:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000698 self.rpcclt.remotequeue("exec", "runcode", (code,), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000699 else:
Georg Brandl7cae87c2006-09-06 06:51:57 +0000700 exec(code, self.locals)
Chui Tey5d2af632002-05-26 13:36:41 +0000701 return 1
702
David Scherer7aced172000-08-15 01:13:23 +0000703 def runcode(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000704 "Override base class method"
Chui Tey5d2af632002-05-26 13:36:41 +0000705 if self.tkconsole.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000706 self.interp.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000707 self.checklinecache()
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000708 if self.save_warnings_filters is not None:
709 warnings.filters[:] = self.save_warnings_filters
710 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000711 debugger = self.debugger
712 try:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000713 self.tkconsole.beginexecuting()
Thomas Wouterscf297e42007-02-23 15:07:44 +0000714 if not debugger and self.rpcclt is not None:
715 self.active_seq = self.rpcclt.asyncqueue("exec", "runcode",
716 (code,), {})
717 elif debugger:
718 debugger.run(code, self.locals)
719 else:
720 exec(code, self.locals)
721 except SystemExit:
722 if not self.tkconsole.closing:
723 if tkMessageBox.askyesno(
724 "Exit?",
725 "Do you want to exit altogether?",
726 default="yes",
727 master=self.tkconsole.text):
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000728 raise
Thomas Wouterscf297e42007-02-23 15:07:44 +0000729 else:
Guido van Rossum5dc0d972007-02-25 22:37:36 +0000730 self.showtraceback()
Thomas Wouterscf297e42007-02-23 15:07:44 +0000731 else:
732 raise
733 except:
734 if use_subprocess:
735 print("IDLE internal error in runcode()",
736 file=self.tkconsole.stderr)
David Scherer7aced172000-08-15 01:13:23 +0000737 self.showtraceback()
Thomas Wouterscf297e42007-02-23 15:07:44 +0000738 self.tkconsole.endexecuting()
739 else:
740 if self.tkconsole.canceled:
741 self.tkconsole.canceled = False
742 print("KeyboardInterrupt", file=self.tkconsole.stderr)
743 else:
744 self.showtraceback()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000745 finally:
746 if not use_subprocess:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000747 try:
748 self.tkconsole.endexecuting()
749 except AttributeError: # shell may have closed
750 pass
David Scherer7aced172000-08-15 01:13:23 +0000751
752 def write(self, s):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000753 "Override base class method"
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000754 self.tkconsole.stderr.write(s)
David Scherer7aced172000-08-15 01:13:23 +0000755
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000756 def display_port_binding_error(self):
757 tkMessageBox.showerror(
758 "Port Binding Error",
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000759 "IDLE can't bind to a TCP/IP port, which is necessary to "
760 "communicate with its Python execution server. This might be "
761 "because no networking is installed on this computer. "
762 "Run IDLE with the -n command line switch to start without a "
763 "subprocess and refer to Help/IDLE Help 'Running without a "
764 "subprocess' for further details.",
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000765 master=self.tkconsole.text)
766
767 def display_no_subprocess_error(self):
768 tkMessageBox.showerror(
769 "Subprocess Startup Error",
770 "IDLE's subprocess didn't make connection. Either IDLE can't "
771 "start a subprocess or personal firewall software is blocking "
772 "the connection.",
773 master=self.tkconsole.text)
774
775 def display_executing_dialog(self):
776 tkMessageBox.showerror(
777 "Already executing",
778 "The Python Shell window is already executing a command; "
779 "please wait until it is finished.",
780 master=self.tkconsole.text)
781
782
David Scherer7aced172000-08-15 01:13:23 +0000783class PyShell(OutputWindow):
784
785 shell_title = "Python Shell"
786
787 # Override classes
788 ColorDelegator = ModifiedColorDelegator
789 UndoDelegator = ModifiedUndoDelegator
790
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000791 # Override menus
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000792 menu_specs = [
793 ("file", "_File"),
794 ("edit", "_Edit"),
Kurt B. Kaiser4cc5ef52003-01-22 00:23:23 +0000795 ("debug", "_Debug"),
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000796 ("options", "_Options"),
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000797 ("windows", "_Windows"),
798 ("help", "_Help"),
799 ]
David Scherer7aced172000-08-15 01:13:23 +0000800
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000801 if macosxSupport.runningAsOSXApp():
802 del menu_specs[-3]
803 menu_specs[-2] = ("windows", "_Window")
804
805
David Scherer7aced172000-08-15 01:13:23 +0000806 # New classes
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000807 from idlelib.IdleHistory import History
David Scherer7aced172000-08-15 01:13:23 +0000808
809 def __init__(self, flist=None):
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000810 if use_subprocess:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000811 ms = self.menu_specs
812 if ms[2][0] != "shell":
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000813 ms.insert(2, ("shell", "She_ll"))
David Scherer7aced172000-08-15 01:13:23 +0000814 self.interp = ModifiedInterpreter(self)
815 if flist is None:
816 root = Tk()
817 fixwordbreaks(root)
818 root.withdraw()
819 flist = PyShellFileList(root)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000820 #
David Scherer7aced172000-08-15 01:13:23 +0000821 OutputWindow.__init__(self, flist, None, None)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000822 #
Kurt B. Kaiser6af44982005-01-19 00:22:59 +0000823## self.config(usetabs=1, indentwidth=8, context_use_ps1=1)
824 self.usetabs = True
825 # indentwidth must be 8 when using tabs. See note in EditorWindow:
826 self.indentwidth = 8
827 self.context_use_ps1 = True
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000828 #
David Scherer7aced172000-08-15 01:13:23 +0000829 text = self.text
830 text.configure(wrap="char")
831 text.bind("<<newline-and-indent>>", self.enter_callback)
832 text.bind("<<plain-newline-and-indent>>", self.linefeed_callback)
833 text.bind("<<interrupt-execution>>", self.cancel_callback)
David Scherer7aced172000-08-15 01:13:23 +0000834 text.bind("<<end-of-file>>", self.eof_callback)
835 text.bind("<<open-stack-viewer>>", self.open_stack_viewer)
Kurt B. Kaiser57bfe5d2003-05-10 00:09:52 +0000836 text.bind("<<toggle-debugger>>", self.toggle_debugger)
David Scherer7aced172000-08-15 01:13:23 +0000837 text.bind("<<toggle-jit-stack-viewer>>", self.toggle_jit_stack_viewer)
Kurt B. Kaiser8a78cad2007-12-13 03:38:16 +0000838 self.color = color = self.ColorDelegator()
839 self.per.insertfilter(color)
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000840 if use_subprocess:
841 text.bind("<<view-restart>>", self.view_restart_mark)
842 text.bind("<<restart-shell>>", self.restart_shell)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000843 #
David Scherer7aced172000-08-15 01:13:23 +0000844 self.save_stdout = sys.stdout
845 self.save_stderr = sys.stderr
846 self.save_stdin = sys.stdin
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000847 from idlelib import IOBinding
Martin v. Löwisbcc651a2003-06-22 07:52:56 +0000848 self.stdout = PseudoFile(self, "stdout", IOBinding.encoding)
849 self.stderr = PseudoFile(self, "stderr", IOBinding.encoding)
850 self.console = PseudoFile(self, "console", IOBinding.encoding)
Chui Tey5d2af632002-05-26 13:36:41 +0000851 if not use_subprocess:
852 sys.stdout = self.stdout
Kurt B. Kaiser7cec2522007-08-31 04:15:13 +0000853 sys.stderr = self.stderr
Chui Tey5d2af632002-05-26 13:36:41 +0000854 sys.stdin = self
Kurt B. Kaiserf609a342007-12-28 03:57:56 +0000855 try:
856 # page help() text to shell.
857 import pydoc # import must be done here to capture i/o rebinding.
858 # XXX KBK 27Dec07 use a textView someday, but must work w/o subproc
859 pydoc.pager = pydoc.plainpager
860 except:
861 sys.stderr = sys.__stderr__
862 raise
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000863 #
David Scherer7aced172000-08-15 01:13:23 +0000864 self.history = self.History(self.text)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000865 #
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000866 self.pollinterval = 50 # millisec
Chui Tey5d2af632002-05-26 13:36:41 +0000867
Kurt B. Kaiser4d5bc602004-06-06 01:29:22 +0000868 def get_standard_extension_names(self):
869 return idleConf.GetExtensions(shell_only=True)
870
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000871 reading = False
872 executing = False
873 canceled = False
874 endoffile = False
875 closing = False
David Scherer7aced172000-08-15 01:13:23 +0000876
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +0000877 def set_warning_stream(self, stream):
Skip Montanarod9161422004-07-06 21:53:27 +0000878 global warning_stream
879 warning_stream = stream
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +0000880
881 def get_warning_stream(self):
882 return warning_stream
883
David Scherer7aced172000-08-15 01:13:23 +0000884 def toggle_debugger(self, event=None):
885 if self.executing:
886 tkMessageBox.showerror("Don't debug now",
887 "You can only toggle the debugger when idle",
888 master=self.text)
889 self.set_debugger_indicator()
890 return "break"
891 else:
892 db = self.interp.getdebugger()
893 if db:
894 self.close_debugger()
895 else:
896 self.open_debugger()
897
898 def set_debugger_indicator(self):
899 db = self.interp.getdebugger()
900 self.setvar("<<toggle-debugger>>", not not db)
901
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000902 def toggle_jit_stack_viewer(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +0000903 pass # All we need is the variable
904
905 def close_debugger(self):
906 db = self.interp.getdebugger()
907 if db:
908 self.interp.setdebugger(None)
909 db.close()
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000910 if self.interp.rpcclt:
911 RemoteDebugger.close_remote_debugger(self.interp.rpcclt)
David Scherer7aced172000-08-15 01:13:23 +0000912 self.resetoutput()
913 self.console.write("[DEBUG OFF]\n")
914 sys.ps1 = ">>> "
915 self.showprompt()
916 self.set_debugger_indicator()
917
918 def open_debugger(self):
Chui Tey5d2af632002-05-26 13:36:41 +0000919 if self.interp.rpcclt:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000920 dbg_gui = RemoteDebugger.start_remote_debugger(self.interp.rpcclt,
921 self)
922 else:
923 dbg_gui = Debugger.Debugger(self)
924 self.interp.setdebugger(dbg_gui)
925 dbg_gui.load_breakpoints()
Chui Tey5d2af632002-05-26 13:36:41 +0000926 sys.ps1 = "[DEBUG ON]\n>>> "
927 self.showprompt()
928 self.set_debugger_indicator()
929
David Scherer7aced172000-08-15 01:13:23 +0000930 def beginexecuting(self):
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000931 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +0000932 self.resetoutput()
933 self.executing = 1
David Scherer7aced172000-08-15 01:13:23 +0000934
935 def endexecuting(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000936 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +0000937 self.executing = 0
938 self.canceled = 0
Chui Tey5d2af632002-05-26 13:36:41 +0000939 self.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000940
941 def close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000942 "Extend EditorWindow.close()"
David Scherer7aced172000-08-15 01:13:23 +0000943 if self.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000944 response = tkMessageBox.askokcancel(
David Scherer7aced172000-08-15 01:13:23 +0000945 "Kill?",
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000946 "The program is still running!\n Do you want to kill it?",
David Scherer7aced172000-08-15 01:13:23 +0000947 default="ok",
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000948 parent=self.text)
Benjamin Peterson2a691a82008-03-31 01:51:45 +0000949 if response is False:
David Scherer7aced172000-08-15 01:13:23 +0000950 return "cancel"
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +0000951 if self.reading:
952 self.top.quit()
953 self.canceled = True
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000954 self.closing = True
955 # Wait for poll_subprocess() rescheduling to stop
956 self.text.after(2 * self.pollinterval, self.close2)
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000957
958 def close2(self):
959 return EditorWindow.close(self)
David Scherer7aced172000-08-15 01:13:23 +0000960
961 def _close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000962 "Extend EditorWindow._close(), shut down debugger and execution server"
David Scherer7aced172000-08-15 01:13:23 +0000963 self.close_debugger()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000964 if use_subprocess:
965 self.interp.kill_subprocess()
David Scherer7aced172000-08-15 01:13:23 +0000966 # Restore std streams
967 sys.stdout = self.save_stdout
968 sys.stderr = self.save_stderr
969 sys.stdin = self.save_stdin
970 # Break cycles
971 self.interp = None
972 self.console = None
David Scherer7aced172000-08-15 01:13:23 +0000973 self.flist.pyshell = None
974 self.history = None
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000975 EditorWindow._close(self)
David Scherer7aced172000-08-15 01:13:23 +0000976
977 def ispythonsource(self, filename):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000978 "Override EditorWindow method: never remove the colorizer"
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000979 return True
David Scherer7aced172000-08-15 01:13:23 +0000980
981 def short_title(self):
982 return self.shell_title
983
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000984 COPYRIGHT = \
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000985 'Type "copyright", "credits" or "license()" for more information.'
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000986
David Scherer7aced172000-08-15 01:13:23 +0000987 def begin(self):
Kurt B. Kaiser7378df72007-08-11 04:20:51 +0000988 self.text.mark_set("iomark", "insert")
David Scherer7aced172000-08-15 01:13:23 +0000989 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000990 if use_subprocess:
991 nosub = ''
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000992 client = self.interp.start_subprocess()
993 if not client:
994 self.close()
Kurt B. Kaiser76637292004-01-21 22:10:01 +0000995 return False
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000996 else:
997 nosub = "==== No Subprocess ===="
Raymond Hettingera2a8e8b2009-01-27 00:28:36 +0000998 self.write("Python %s on %s\n%s\n%s" %
999 (sys.version, sys.platform, self.COPYRIGHT, nosub))
David Scherer7aced172000-08-15 01:13:23 +00001000 self.showprompt()
Georg Brandl14fc4272008-05-17 18:39:55 +00001001 import tkinter
1002 tkinter._default_root = None # 03Jan04 KBK What's this?
Kurt B. Kaiser76637292004-01-21 22:10:01 +00001003 return True
David Scherer7aced172000-08-15 01:13:23 +00001004
1005 def readline(self):
1006 save = self.reading
1007 try:
1008 self.reading = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001009 self.top.mainloop() # nested mainloop()
David Scherer7aced172000-08-15 01:13:23 +00001010 finally:
1011 self.reading = save
1012 line = self.text.get("iomark", "end-1c")
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001013 if len(line) == 0: # may be EOF if we quit our mainloop with Ctrl-C
1014 line = "\n"
David Scherer7aced172000-08-15 01:13:23 +00001015 self.resetoutput()
1016 if self.canceled:
1017 self.canceled = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001018 if not use_subprocess:
1019 raise KeyboardInterrupt
David Scherer7aced172000-08-15 01:13:23 +00001020 if self.endoffile:
1021 self.endoffile = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001022 line = ""
David Scherer7aced172000-08-15 01:13:23 +00001023 return line
1024
1025 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001026 return True
David Scherer7aced172000-08-15 01:13:23 +00001027
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001028 def cancel_callback(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +00001029 try:
1030 if self.text.compare("sel.first", "!=", "sel.last"):
1031 return # Active selection -- always use default binding
1032 except:
1033 pass
1034 if not (self.executing or self.reading):
1035 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001036 self.interp.write("KeyboardInterrupt\n")
David Scherer7aced172000-08-15 01:13:23 +00001037 self.showprompt()
1038 return "break"
1039 self.endoffile = 0
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001040 self.canceled = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001041 if (self.executing and self.interp.rpcclt):
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +00001042 if self.interp.getdebugger():
1043 self.interp.restart_subprocess()
1044 else:
1045 self.interp.interrupt_subprocess()
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001046 if self.reading:
1047 self.top.quit() # exit the nested mainloop() in readline()
David Scherer7aced172000-08-15 01:13:23 +00001048 return "break"
1049
1050 def eof_callback(self, event):
1051 if self.executing and not self.reading:
1052 return # Let the default binding (delete next char) take over
1053 if not (self.text.compare("iomark", "==", "insert") and
1054 self.text.compare("insert", "==", "end-1c")):
1055 return # Let the default binding (delete next char) take over
1056 if not self.executing:
David Scherer7aced172000-08-15 01:13:23 +00001057 self.resetoutput()
1058 self.close()
1059 else:
1060 self.canceled = 0
1061 self.endoffile = 1
1062 self.top.quit()
1063 return "break"
1064
David Scherer7aced172000-08-15 01:13:23 +00001065 def linefeed_callback(self, event):
1066 # Insert a linefeed without entering anything (still autoindented)
1067 if self.reading:
1068 self.text.insert("insert", "\n")
1069 self.text.see("insert")
1070 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001071 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001072 return "break"
1073
1074 def enter_callback(self, event):
1075 if self.executing and not self.reading:
1076 return # Let the default binding (insert '\n') take over
1077 # If some text is selected, recall the selection
1078 # (but only if this before the I/O mark)
1079 try:
1080 sel = self.text.get("sel.first", "sel.last")
1081 if sel:
1082 if self.text.compare("sel.last", "<=", "iomark"):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001083 self.recall(sel, event)
David Scherer7aced172000-08-15 01:13:23 +00001084 return "break"
1085 except:
1086 pass
1087 # If we're strictly before the line containing iomark, recall
1088 # the current line, less a leading prompt, less leading or
1089 # trailing whitespace
1090 if self.text.compare("insert", "<", "iomark linestart"):
1091 # Check if there's a relevant stdin range -- if so, use it
1092 prev = self.text.tag_prevrange("stdin", "insert")
1093 if prev and self.text.compare("insert", "<", prev[1]):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001094 self.recall(self.text.get(prev[0], prev[1]), event)
David Scherer7aced172000-08-15 01:13:23 +00001095 return "break"
1096 next = self.text.tag_nextrange("stdin", "insert")
1097 if next and self.text.compare("insert lineend", ">=", next[0]):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001098 self.recall(self.text.get(next[0], next[1]), event)
David Scherer7aced172000-08-15 01:13:23 +00001099 return "break"
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001100 # No stdin mark -- just get the current line, less any prompt
Kurt B. Kaiserb1754452005-11-18 22:05:48 +00001101 indices = self.text.tag_nextrange("console", "insert linestart")
1102 if indices and \
1103 self.text.compare(indices[0], "<=", "insert linestart"):
1104 self.recall(self.text.get(indices[1], "insert lineend"), event)
1105 else:
1106 self.recall(self.text.get("insert linestart", "insert lineend"), event)
David Scherer7aced172000-08-15 01:13:23 +00001107 return "break"
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001108 # If we're between the beginning of the line and the iomark, i.e.
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001109 # in the prompt area, move to the end of the prompt
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001110 if self.text.compare("insert", "<", "iomark"):
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001111 self.text.mark_set("insert", "iomark")
David Scherer7aced172000-08-15 01:13:23 +00001112 # If we're in the current input and there's only whitespace
1113 # beyond the cursor, erase that whitespace first
1114 s = self.text.get("insert", "end-1c")
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001115 if s and not s.strip():
David Scherer7aced172000-08-15 01:13:23 +00001116 self.text.delete("insert", "end-1c")
1117 # If we're in the current input before its last line,
1118 # insert a newline right at the insert point
1119 if self.text.compare("insert", "<", "end-1c linestart"):
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001120 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001121 return "break"
1122 # We're in the last line; append a newline and submit it
1123 self.text.mark_set("insert", "end-1c")
1124 if self.reading:
1125 self.text.insert("insert", "\n")
1126 self.text.see("insert")
1127 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001128 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001129 self.text.tag_add("stdin", "iomark", "end-1c")
1130 self.text.update_idletasks()
1131 if self.reading:
Neal Norwitzce96f692006-03-17 06:49:51 +00001132 self.top.quit() # Break out of recursive mainloop()
David Scherer7aced172000-08-15 01:13:23 +00001133 else:
1134 self.runit()
1135 return "break"
1136
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001137 def recall(self, s, event):
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001138 # remove leading and trailing empty or whitespace lines
1139 s = re.sub(r'^\s*\n', '' , s)
1140 s = re.sub(r'\n\s*$', '', s)
1141 lines = s.split('\n')
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001142 self.text.undo_block_start()
1143 try:
1144 self.text.tag_remove("sel", "1.0", "end")
1145 self.text.mark_set("insert", "end-1c")
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001146 prefix = self.text.get("insert linestart", "insert")
1147 if prefix.rstrip().endswith(':'):
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001148 self.newline_and_indent_event(event)
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001149 prefix = self.text.get("insert linestart", "insert")
1150 self.text.insert("insert", lines[0].strip())
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001151 if len(lines) > 1:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001152 orig_base_indent = re.search(r'^([ \t]*)', lines[0]).group(0)
1153 new_base_indent = re.search(r'^([ \t]*)', prefix).group(0)
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001154 for line in lines[1:]:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001155 if line.startswith(orig_base_indent):
1156 # replace orig base indentation with new indentation
1157 line = new_base_indent + line[len(orig_base_indent):]
1158 self.text.insert('insert', '\n'+line.rstrip())
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001159 finally:
1160 self.text.see("insert")
1161 self.text.undo_block_stop()
David Scherer7aced172000-08-15 01:13:23 +00001162
1163 def runit(self):
1164 line = self.text.get("iomark", "end-1c")
1165 # Strip off last newline and surrounding whitespace.
1166 # (To allow you to hit return twice to end a statement.)
1167 i = len(line)
1168 while i > 0 and line[i-1] in " \t":
1169 i = i-1
1170 if i > 0 and line[i-1] == "\n":
1171 i = i-1
1172 while i > 0 and line[i-1] in " \t":
1173 i = i-1
1174 line = line[:i]
1175 more = self.interp.runsource(line)
David Scherer7aced172000-08-15 01:13:23 +00001176
David Scherer7aced172000-08-15 01:13:23 +00001177 def open_stack_viewer(self, event=None):
Chui Tey5d2af632002-05-26 13:36:41 +00001178 if self.interp.rpcclt:
1179 return self.interp.remote_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +00001180 try:
1181 sys.last_traceback
1182 except:
1183 tkMessageBox.showerror("No stack trace",
1184 "There is no stack trace yet.\n"
1185 "(sys.last_traceback is not defined)",
1186 master=self.text)
1187 return
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +00001188 from idlelib.StackViewer import StackBrowser
David Scherer7aced172000-08-15 01:13:23 +00001189 sv = StackBrowser(self.root, self.flist)
1190
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001191 def view_restart_mark(self, event=None):
1192 self.text.see("iomark")
1193 self.text.see("restart")
1194
1195 def restart_shell(self, event=None):
Terry Jan Reedyda4c4672012-01-31 02:26:32 -05001196 "Callback for Run/Restart Shell Cntl-F6"
1197 self.interp.restart_subprocess(with_cwd=True)
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001198
David Scherer7aced172000-08-15 01:13:23 +00001199 def showprompt(self):
1200 self.resetoutput()
1201 try:
1202 s = str(sys.ps1)
1203 except:
1204 s = ""
1205 self.console.write(s)
1206 self.text.mark_set("insert", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001207 self.set_line_and_column()
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +00001208 self.io.reset_undo()
David Scherer7aced172000-08-15 01:13:23 +00001209
1210 def resetoutput(self):
1211 source = self.text.get("iomark", "end-1c")
1212 if self.history:
1213 self.history.history_store(source)
1214 if self.text.get("end-2c") != "\n":
1215 self.text.insert("end-1c", "\n")
1216 self.text.mark_set("iomark", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001217 self.set_line_and_column()
David Scherer7aced172000-08-15 01:13:23 +00001218
1219 def write(self, s, tags=()):
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001220 try:
1221 self.text.mark_gravity("iomark", "right")
1222 OutputWindow.write(self, s, tags, "iomark")
1223 self.text.mark_gravity("iomark", "left")
1224 except:
Kurt B. Kaisercbbe98f2007-08-12 01:52:35 +00001225 raise ###pass # ### 11Aug07 KBK if we are expecting exceptions
1226 # let's find out what they are and be specific.
David Scherer7aced172000-08-15 01:13:23 +00001227 if self.canceled:
1228 self.canceled = 0
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001229 if not use_subprocess:
1230 raise KeyboardInterrupt
David Scherer7aced172000-08-15 01:13:23 +00001231
Kurt B. Kaiserdcba6622004-12-21 22:10:32 +00001232class PseudoFile(object):
David Scherer7aced172000-08-15 01:13:23 +00001233
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001234 def __init__(self, shell, tags, encoding=None):
David Scherer7aced172000-08-15 01:13:23 +00001235 self.shell = shell
1236 self.tags = tags
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001237 self.encoding = encoding
David Scherer7aced172000-08-15 01:13:23 +00001238
1239 def write(self, s):
1240 self.shell.write(s, self.tags)
1241
Kurt B. Kaiser66aaf742007-08-09 18:00:23 +00001242 def writelines(self, lines):
1243 for line in lines:
1244 self.write(line)
David Scherer7aced172000-08-15 01:13:23 +00001245
1246 def flush(self):
1247 pass
1248
1249 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001250 return True
David Scherer7aced172000-08-15 01:13:23 +00001251
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001252
David Scherer7aced172000-08-15 01:13:23 +00001253usage_msg = """\
David Scherer7aced172000-08-15 01:13:23 +00001254
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001255USAGE: idle [-deins] [-t title] [file]*
1256 idle [-dns] [-t title] (-c cmd | -r file) [arg]*
1257 idle [-dns] [-t title] - [arg]*
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001258
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001259 -h print this help message and exit
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001260 -n run IDLE without a subprocess (see Help/IDLE Help for details)
David Scherer7aced172000-08-15 01:13:23 +00001261
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001262The following options will override the IDLE 'settings' configuration:
Kurt B. Kaiser96d88422001-07-17 04:59:01 +00001263
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001264 -e open an edit window
1265 -i open a shell window
1266
1267The following options imply -i and will open a shell:
1268
1269 -c cmd run the command in a shell, or
1270 -r file run script from file
1271
1272 -d enable the debugger
1273 -s run $IDLESTARTUP or $PYTHONSTARTUP before anything else
1274 -t title set title of shell window
1275
1276A default edit window will be bypassed when -c, -r, or - are used.
1277
1278[arg]* are passed to the command (-c) or script (-r) in sys.argv[1:].
1279
1280Examples:
1281
1282idle
1283 Open an edit window or shell depending on IDLE's configuration.
1284
1285idle foo.py foobar.py
1286 Edit the files, also open a shell if configured to start with shell.
1287
1288idle -est "Baz" foo.py
1289 Run $IDLESTARTUP or $PYTHONSTARTUP, edit foo.py, and open a shell
1290 window with the title "Baz".
1291
Neal Norwitz752abd02008-05-13 04:55:24 +00001292idle -c "import sys; print(sys.argv)" "foo"
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001293 Open a shell window and run the command, passing "-c" in sys.argv[0]
1294 and "foo" in sys.argv[1].
1295
1296idle -d -s -r foo.py "Hello World"
1297 Open a shell window, run a startup script, enable the debugger, and
1298 run foo.py, passing "foo.py" in sys.argv[0] and "Hello World" in
1299 sys.argv[1].
1300
Neal Norwitz752abd02008-05-13 04:55:24 +00001301echo "import sys; print(sys.argv)" | idle - "foobar"
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001302 Open a shell window, run the script piped in, passing '' in sys.argv[0]
1303 and "foobar" in sys.argv[1].
David Scherer7aced172000-08-15 01:13:23 +00001304"""
1305
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001306def main():
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001307 global flist, root, use_subprocess
David Scherer7aced172000-08-15 01:13:23 +00001308
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001309 use_subprocess = True
Kurt B. Kaisere866c812009-04-04 21:07:39 +00001310 enable_shell = True
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001311 enable_edit = False
1312 debug = False
1313 cmd = None
1314 script = None
1315 startup = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001316 try:
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001317 opts, args = getopt.getopt(sys.argv[1:], "c:deihnr:st:")
Guido van Rossumb940e112007-01-10 16:19:56 +00001318 except getopt.error as msg:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001319 sys.stderr.write("Error: %s\n" % str(msg))
1320 sys.stderr.write(usage_msg)
1321 sys.exit(2)
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001322 for o, a in opts:
1323 if o == '-c':
1324 cmd = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001325 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001326 if o == '-d':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001327 debug = True
1328 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001329 if o == '-e':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001330 enable_edit = True
Kurt B. Kaisere866c812009-04-04 21:07:39 +00001331 enable_shell = False
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001332 if o == '-h':
1333 sys.stdout.write(usage_msg)
1334 sys.exit()
1335 if o == '-i':
1336 enable_shell = True
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001337 if o == '-n':
1338 use_subprocess = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001339 if o == '-r':
1340 script = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001341 if os.path.isfile(script):
1342 pass
1343 else:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001344 print("No script file: ", script)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001345 sys.exit()
1346 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001347 if o == '-s':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001348 startup = True
1349 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001350 if o == '-t':
1351 PyShell.shell_title = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001352 enable_shell = True
1353 if args and args[0] == '-':
1354 cmd = sys.stdin.read()
1355 enable_shell = True
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001356 # process sys.argv and sys.path:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001357 for i in range(len(sys.path)):
1358 sys.path[i] = os.path.abspath(sys.path[i])
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001359 if args and args[0] == '-':
1360 sys.argv = [''] + args[1:]
1361 elif cmd:
1362 sys.argv = ['-c'] + args
1363 elif script:
1364 sys.argv = [script] + args
1365 elif args:
1366 enable_edit = True
1367 pathx = []
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001368 for filename in args:
1369 pathx.append(os.path.dirname(filename))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001370 for dir in pathx:
1371 dir = os.path.abspath(dir)
1372 if not dir in sys.path:
1373 sys.path.insert(0, dir)
Kurt B. Kaiserff002b92002-12-21 21:39:11 +00001374 else:
Neal Norwitzd082b6e2007-08-26 23:37:53 +00001375 dir = os.getcwd()
1376 if dir not in sys.path:
Kurt B. Kaiserff002b92002-12-21 21:39:11 +00001377 sys.path.insert(0, dir)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001378 # check the IDLE settings configuration (but command line overrides)
1379 edit_start = idleConf.GetOption('main', 'General',
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001380 'editor-on-startup', type='bool')
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001381 enable_edit = enable_edit or edit_start
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001382 # start editor and/or shell windows:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001383 root = Tk(className="Idle")
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001384
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001385 fixwordbreaks(root)
1386 root.withdraw()
1387 flist = PyShellFileList(root)
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001388 macosxSupport.setupApp(root, flist)
1389
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001390 if enable_edit:
1391 if not (cmd or script):
1392 for filename in args:
1393 flist.open(filename)
1394 if not args:
1395 flist.new()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001396 if enable_shell:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001397 shell = flist.open_shell()
1398 if not shell:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001399 return # couldn't open shell
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001400
1401 if macosxSupport.runningAsOSXApp() and flist.dict:
1402 # On OSX: when the user has double-clicked on a file that causes
1403 # IDLE to be launched the shell window will open just in front of
1404 # the file she wants to see. Lower the interpreter window when
1405 # there are open files.
1406 shell.top.lower()
1407
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001408 shell = flist.pyshell
1409 # handle remaining options:
1410 if debug:
1411 shell.open_debugger()
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001412 if startup:
1413 filename = os.environ.get("IDLESTARTUP") or \
1414 os.environ.get("PYTHONSTARTUP")
1415 if filename and os.path.isfile(filename):
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001416 shell.interp.execfile(filename)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001417 if shell and cmd or script:
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001418 shell.interp.runcommand("""if 1:
1419 import sys as _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001420 _sys.argv = %r
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001421 del _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001422 \n""" % (sys.argv,))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001423 if cmd:
1424 shell.interp.execsource(cmd)
1425 elif script:
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001426 shell.interp.prepend_syspath(script)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001427 shell.interp.execfile(script)
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001428
Ned Deily4ce92b22011-01-15 04:37:12 +00001429 # Check for problematic OS X Tk versions and print a warning message
1430 # in the IDLE shell window; this is less intrusive than always opening
1431 # a separate window.
1432 tkversionwarning = macosxSupport.tkVersionWarning(root)
1433 if tkversionwarning:
1434 shell.interp.runcommand(''.join(("print('", tkversionwarning, "')")))
1435
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001436 root.mainloop()
1437 root.destroy()
1438
David Scherer7aced172000-08-15 01:13:23 +00001439if __name__ == "__main__":
Kurt B. Kaiser9e8b8282003-06-15 17:38:45 +00001440 sys.modules['PyShell'] = sys.modules['__main__']
David Scherer7aced172000-08-15 01:13:23 +00001441 main()