blob: 0eae7c5cee38876a86af8e84c8cb48186e272437 [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
Martin v. Löwisc882b7c2012-07-25 10:47:20 +020015import io
David Scherer7aced172000-08-15 01:13:23 +000016
17import linecache
18from code import InteractiveInterpreter
19
Kurt B. Kaiser2303b1c2003-11-24 05:26:16 +000020try:
Georg Brandl14fc4272008-05-17 18:39:55 +000021 from tkinter import *
Kurt B. Kaiser2303b1c2003-11-24 05:26:16 +000022except ImportError:
Guido van Rossumbe19ed72007-02-09 05:37:30 +000023 print("** IDLE can't import Tkinter. " \
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +000024 "Your Python may not be configured for Tk. **", file=sys.__stderr__)
Kurt B. Kaiser2303b1c2003-11-24 05:26:16 +000025 sys.exit(1)
Georg Brandl14fc4272008-05-17 18:39:55 +000026import tkinter.messagebox as tkMessageBox
David Scherer7aced172000-08-15 01:13:23 +000027
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +000028from idlelib.EditorWindow import EditorWindow, fixwordbreaks
29from idlelib.FileList import FileList
30from idlelib.ColorDelegator import ColorDelegator
31from idlelib.UndoDelegator import UndoDelegator
32from idlelib.OutputWindow import OutputWindow
33from idlelib.configHandler import idleConf
34from idlelib import idlever
35from idlelib import rpc
36from idlelib import Debugger
37from idlelib import RemoteDebugger
38from idlelib import macosxSupport
Chui Tey5d2af632002-05-26 13:36:41 +000039
Kurt B. Kaisere866c812009-04-04 21:07:39 +000040HOST = '127.0.0.1' # python execution server on localhost loopback
41PORT = 0 # someday pass in host, port for remote debug capability
Kurt B. Kaiserb9764192002-09-23 04:10:37 +000042
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000043# Override warnings module to write to warning_stream. Initialize to send IDLE
44# internal warnings to the console. ScriptBinding.check_syntax() will
45# temporarily redirect the stream to the shell window to display warnings when
46# checking user's code.
47global warning_stream
48warning_stream = sys.__stderr__
Chui Tey5d2af632002-05-26 13:36:41 +000049try:
50 import warnings
51except ImportError:
52 pass
53else:
Benjamin Peterson206e3072008-10-19 14:07:49 +000054 def idle_showwarning(message, category, filename, lineno,
55 file=None, line=None):
Guilherme Polo1fff0082009-08-14 15:05:30 +000056 if file is None:
57 file = warning_stream
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000058 try:
Guilherme Polo1fff0082009-08-14 15:05:30 +000059 file.write(warnings.formatwarning(message, category, filename,
Senthil Kumaranaa90e7c2011-07-03 17:39:20 -070060 lineno, line=line))
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000061 except IOError:
62 pass ## file (probably __stderr__) is invalid, warning dropped.
Chui Tey5d2af632002-05-26 13:36:41 +000063 warnings.showwarning = idle_showwarning
Guilherme Polo1fff0082009-08-14 15:05:30 +000064 def idle_formatwarning(message, category, filename, lineno, line=None):
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000065 """Format warnings the IDLE way"""
66 s = "\nWarning (from warnings module):\n"
67 s += ' File \"%s\", line %s\n' % (filename, lineno)
Guilherme Polo1fff0082009-08-14 15:05:30 +000068 if line is None:
69 line = linecache.getline(filename, lineno)
70 line = line.strip()
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000071 if line:
72 s += " %s\n" % line
73 s += "%s: %s\n>>> " % (category.__name__, message)
74 return s
75 warnings.formatwarning = idle_formatwarning
Chui Tey5d2af632002-05-26 13:36:41 +000076
Kurt B. Kaiserf7a88992004-11-13 21:05:58 +000077def extended_linecache_checkcache(filename=None,
78 orig_checkcache=linecache.checkcache):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +000079 """Extend linecache.checkcache to preserve the <pyshell#...> entries
80
Kurt B. Kaiserf7a88992004-11-13 21:05:58 +000081 Rather than repeating the linecache code, patch it to save the
82 <pyshell#...> entries, call the original linecache.checkcache()
Guilherme Polo1fff0082009-08-14 15:05:30 +000083 (skipping them), and then restore the saved entries.
Kurt B. Kaiserf7a88992004-11-13 21:05:58 +000084
85 orig_checkcache is bound at definition time to the original
86 method, allowing it to be patched.
Kurt B. Kaiser45186c42002-10-23 04:48:08 +000087 """
David Scherer7aced172000-08-15 01:13:23 +000088 cache = linecache.cache
89 save = {}
Guilherme Polo1fff0082009-08-14 15:05:30 +000090 for key in list(cache):
91 if key[:1] + key[-1:] == '<>':
92 save[key] = cache.pop(key)
93 orig_checkcache(filename)
David Scherer7aced172000-08-15 01:13:23 +000094 cache.update(save)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +000095
Kurt B. Kaiser81885592002-11-29 22:10:53 +000096# Patch linecache.checkcache():
97linecache.checkcache = extended_linecache_checkcache
David Scherer7aced172000-08-15 01:13:23 +000098
Kurt B. Kaiser45186c42002-10-23 04:48:08 +000099
David Scherer7aced172000-08-15 01:13:23 +0000100class PyShellEditorWindow(EditorWindow):
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000101 "Regular text edit window in IDLE, supports breakpoints"
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000102
David Scherer7aced172000-08-15 01:13:23 +0000103 def __init__(self, *args):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000104 self.breakpoints = []
Raymond Hettinger931237e2003-07-09 18:48:24 +0000105 EditorWindow.__init__(self, *args)
David Scherer7aced172000-08-15 01:13:23 +0000106 self.text.bind("<<set-breakpoint-here>>", self.set_breakpoint_here)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000107 self.text.bind("<<clear-breakpoint-here>>", self.clear_breakpoint_here)
David Scherer7aced172000-08-15 01:13:23 +0000108 self.text.bind("<<open-python-shell>>", self.flist.open_shell)
109
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000110 self.breakpointPath = os.path.join(idleConf.GetUserCfgDir(),
111 'breakpoints.lst')
Chui Teya2adb0f2002-11-04 22:14:54 +0000112 # whenever a file is changed, restore breakpoints
113 if self.io.filename: self.restore_file_breaks()
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000114 def filename_changed_hook(old_hook=self.io.filename_change_hook,
115 self=self):
Chui Teya2adb0f2002-11-04 22:14:54 +0000116 self.restore_file_breaks()
117 old_hook()
118 self.io.set_filename_change_hook(filename_changed_hook)
119
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000120 rmenu_specs = [("Set Breakpoint", "<<set-breakpoint-here>>"),
121 ("Clear Breakpoint", "<<clear-breakpoint-here>>")]
David Scherer7aced172000-08-15 01:13:23 +0000122
Chui Teya2adb0f2002-11-04 22:14:54 +0000123 def set_breakpoint(self, lineno):
124 text = self.text
125 filename = self.io.filename
126 text.tag_add("BREAK", "%d.0" % lineno, "%d.0" % (lineno+1))
127 try:
128 i = self.breakpoints.index(lineno)
129 except ValueError: # only add if missing, i.e. do once
130 self.breakpoints.append(lineno)
131 try: # update the subprocess debugger
132 debug = self.flist.pyshell.interp.debugger
133 debug.set_breakpoint_here(filename, lineno)
134 except: # but debugger may not be active right now....
135 pass
136
David Scherer7aced172000-08-15 01:13:23 +0000137 def set_breakpoint_here(self, event=None):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000138 text = self.text
139 filename = self.io.filename
140 if not filename:
141 text.bell()
David Scherer7aced172000-08-15 01:13:23 +0000142 return
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000143 lineno = int(float(text.index("insert")))
Chui Teya2adb0f2002-11-04 22:14:54 +0000144 self.set_breakpoint(lineno)
David Scherer7aced172000-08-15 01:13:23 +0000145
Kurt B. Kaiser669f4c32002-06-20 04:01:47 +0000146 def clear_breakpoint_here(self, event=None):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000147 text = self.text
148 filename = self.io.filename
149 if not filename:
150 text.bell()
Kurt B. Kaiser669f4c32002-06-20 04:01:47 +0000151 return
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000152 lineno = int(float(text.index("insert")))
153 try:
154 self.breakpoints.remove(lineno)
155 except:
156 pass
157 text.tag_remove("BREAK", "insert linestart",\
158 "insert lineend +1char")
159 try:
160 debug = self.flist.pyshell.interp.debugger
161 debug.clear_breakpoint_here(filename, lineno)
162 except:
163 pass
164
165 def clear_file_breaks(self):
166 if self.breakpoints:
167 text = self.text
168 filename = self.io.filename
169 if not filename:
170 text.bell()
171 return
172 self.breakpoints = []
173 text.tag_remove("BREAK", "1.0", END)
174 try:
175 debug = self.flist.pyshell.interp.debugger
176 debug.clear_file_breaks(filename)
177 except:
178 pass
179
Chui Teya2adb0f2002-11-04 22:14:54 +0000180 def store_file_breaks(self):
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000181 "Save breakpoints when file is saved"
182 # XXX 13 Dec 2002 KBK Currently the file must be saved before it can
183 # be run. The breaks are saved at that time. If we introduce
184 # a temporary file save feature the save breaks functionality
185 # needs to be re-verified, since the breaks at the time the
186 # temp file is created may differ from the breaks at the last
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000187 # permanent save of the file. Currently, a break introduced
188 # after a save will be effective, but not persistent.
189 # This is necessary to keep the saved breaks synched with the
190 # saved file.
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000191 #
192 # Breakpoints are set as tagged ranges in the text. Certain
193 # kinds of edits cause these ranges to be deleted: Inserting
194 # or deleting a line just before a breakpoint, and certain
195 # deletions prior to a breakpoint. These issues need to be
196 # investigated and understood. It's not clear if they are
197 # Tk issues or IDLE issues, or whether they can actually
198 # be fixed. Since a modified file has to be saved before it is
199 # run, and since self.breakpoints (from which the subprocess
200 # debugger is loaded) is updated during the save, the visible
201 # breaks stay synched with the subprocess even if one of these
202 # unexpected breakpoint deletions occurs.
203 breaks = self.breakpoints
204 filename = self.io.filename
Chui Teya2adb0f2002-11-04 22:14:54 +0000205 try:
Victor Stinner85c67722011-09-02 00:57:04 +0200206 with open(self.breakpointPath, "r") as fp:
207 lines = fp.readlines()
Chui Teya2adb0f2002-11-04 22:14:54 +0000208 except IOError:
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000209 lines = []
Ned Deilyf505b742011-12-14 14:58:24 -0800210 try:
211 with open(self.breakpointPath, "w") as new_file:
212 for line in lines:
213 if not line.startswith(filename + '='):
214 new_file.write(line)
215 self.update_breakpoints()
216 breaks = self.breakpoints
217 if breaks:
218 new_file.write(filename + '=' + str(breaks) + '\n')
219 except IOError as err:
220 if not getattr(self.root, "breakpoint_error_displayed", False):
221 self.root.breakpoint_error_displayed = True
222 tkMessageBox.showerror(title='IDLE Error',
223 message='Unable to update breakpoint list:\n%s'
224 % str(err),
225 parent=self.text)
Chui Teya2adb0f2002-11-04 22:14:54 +0000226
227 def restore_file_breaks(self):
228 self.text.update() # this enables setting "BREAK" tags to be visible
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000229 filename = self.io.filename
230 if filename is None:
231 return
Chui Tey69371d62002-11-04 23:39:45 +0000232 if os.path.isfile(self.breakpointPath):
Victor Stinner85c67722011-09-02 00:57:04 +0200233 with open(self.breakpointPath, "r") as fp:
234 lines = fp.readlines()
Chui Tey69371d62002-11-04 23:39:45 +0000235 for line in lines:
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000236 if line.startswith(filename + '='):
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000237 breakpoint_linenumbers = eval(line[len(filename)+1:])
Chui Tey69371d62002-11-04 23:39:45 +0000238 for breakpoint_linenumber in breakpoint_linenumbers:
239 self.set_breakpoint(breakpoint_linenumber)
Chui Teya2adb0f2002-11-04 22:14:54 +0000240
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000241 def update_breakpoints(self):
242 "Retrieves all the breakpoints in the current window"
Chui Teya2adb0f2002-11-04 22:14:54 +0000243 text = self.text
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000244 ranges = text.tag_ranges("BREAK")
245 linenumber_list = self.ranges_to_linenumbers(ranges)
246 self.breakpoints = linenumber_list
247
248 def ranges_to_linenumbers(self, ranges):
249 lines = []
250 for index in range(0, len(ranges), 2):
251 lineno = int(float(ranges[index]))
252 end = int(float(ranges[index+1]))
253 while lineno < end:
254 lines.append(lineno)
255 lineno += 1
256 return lines
257
Kurt B. Kaiser11220fa2002-12-24 00:57:22 +0000258# XXX 13 Dec 2002 KBK Not used currently
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000259# def saved_change_hook(self):
260# "Extend base method - clear breaks if module is modified"
261# if not self.get_saved():
262# self.clear_file_breaks()
263# EditorWindow.saved_change_hook(self)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000264
265 def _close(self):
266 "Extend base method - clear breaks when module is closed"
267 self.clear_file_breaks()
268 EditorWindow._close(self)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000269
David Scherer7aced172000-08-15 01:13:23 +0000270
271class PyShellFileList(FileList):
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000272 "Extend base class: IDLE supports a shell and breakpoints"
David Scherer7aced172000-08-15 01:13:23 +0000273
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000274 # override FileList's class variable, instances return PyShellEditorWindow
275 # instead of EditorWindow when new edit windows are created.
David Scherer7aced172000-08-15 01:13:23 +0000276 EditorWindow = PyShellEditorWindow
277
278 pyshell = None
279
280 def open_shell(self, event=None):
281 if self.pyshell:
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000282 self.pyshell.top.wakeup()
David Scherer7aced172000-08-15 01:13:23 +0000283 else:
284 self.pyshell = PyShell(self)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000285 if self.pyshell:
286 if not self.pyshell.begin():
287 return None
David Scherer7aced172000-08-15 01:13:23 +0000288 return self.pyshell
289
290
291class ModifiedColorDelegator(ColorDelegator):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000292 "Extend base class: colorizer for the shell window itself"
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000293
Steven M. Gavab77d3432002-03-02 07:16:21 +0000294 def __init__(self):
295 ColorDelegator.__init__(self)
296 self.LoadTagDefs()
David Scherer7aced172000-08-15 01:13:23 +0000297
298 def recolorize_main(self):
299 self.tag_remove("TODO", "1.0", "iomark")
300 self.tag_add("SYNC", "1.0", "iomark")
301 ColorDelegator.recolorize_main(self)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000302
Steven M. Gavab77d3432002-03-02 07:16:21 +0000303 def LoadTagDefs(self):
304 ColorDelegator.LoadTagDefs(self)
305 theme = idleConf.GetOption('main','Theme','name')
306 self.tagdefs.update({
307 "stdin": {'background':None,'foreground':None},
308 "stdout": idleConf.GetHighlight(theme, "stdout"),
309 "stderr": idleConf.GetHighlight(theme, "stderr"),
310 "console": idleConf.GetHighlight(theme, "console"),
Steven M. Gavab77d3432002-03-02 07:16:21 +0000311 })
David Scherer7aced172000-08-15 01:13:23 +0000312
Ned Deily8b2a56b2012-05-31 09:17:29 -0700313 def removecolors(self):
314 # Don't remove shell color tags before "iomark"
315 for tag in self.tagdefs:
316 self.tag_remove(tag, "iomark", "end")
317
David Scherer7aced172000-08-15 01:13:23 +0000318class ModifiedUndoDelegator(UndoDelegator):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000319 "Extend base class: forbid insert/delete before the I/O mark"
David Scherer7aced172000-08-15 01:13:23 +0000320
321 def insert(self, index, chars, tags=None):
322 try:
323 if self.delegate.compare(index, "<", "iomark"):
324 self.delegate.bell()
325 return
326 except TclError:
327 pass
328 UndoDelegator.insert(self, index, chars, tags)
329
330 def delete(self, index1, index2=None):
331 try:
332 if self.delegate.compare(index1, "<", "iomark"):
333 self.delegate.bell()
334 return
335 except TclError:
336 pass
337 UndoDelegator.delete(self, index1, index2)
338
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000339
340class MyRPCClient(rpc.RPCClient):
341
342 def handle_EOF(self):
343 "Override the base class - just re-raise EOFError"
344 raise EOFError
345
Kurt B. Kaiser8d1f11b2003-05-26 22:20:34 +0000346
David Scherer7aced172000-08-15 01:13:23 +0000347class ModifiedInterpreter(InteractiveInterpreter):
348
349 def __init__(self, tkconsole):
350 self.tkconsole = tkconsole
351 locals = sys.modules['__main__'].__dict__
352 InteractiveInterpreter.__init__(self, locals=locals)
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000353 self.save_warnings_filters = None
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000354 self.restarting = False
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000355 self.subprocess_arglist = None
356 self.port = PORT
Ned Deily7aff4512011-10-30 20:01:35 -0700357 self.original_compiler_flags = self.compile.compiler.flags
David Scherer7aced172000-08-15 01:13:23 +0000358
Chui Tey5d2af632002-05-26 13:36:41 +0000359 rpcclt = None
Ned Deilye5cad232011-08-02 18:47:13 -0700360 rpcsubproc = None
Chui Tey5d2af632002-05-26 13:36:41 +0000361
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000362 def spawn_subprocess(self):
Florent Xiclunafd1b0932010-03-28 00:25:02 +0000363 if self.subprocess_arglist is None:
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000364 self.subprocess_arglist = self.build_subprocess_arglist()
Ned Deilye5cad232011-08-02 18:47:13 -0700365 self.rpcsubproc = subprocess.Popen(self.subprocess_arglist)
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000366
Tony Lowndsf53dec22002-12-20 04:24:43 +0000367 def build_subprocess_arglist(self):
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000368 assert (self.port!=0), (
369 "Socket should have been assigned a port number.")
Tony Lownds2398d572003-05-13 15:28:21 +0000370 w = ['-W' + s for s in sys.warnoptions]
371 # Maybe IDLE is installed and is being accessed via sys.path,
372 # or maybe it's not installed and the idle.py script is being
373 # run from the IDLE source directory.
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000374 del_exitf = idleConf.GetOption('main', 'General', 'delete-exitfunc',
375 default=False, type='bool')
Tony Lownds2398d572003-05-13 15:28:21 +0000376 if __name__ == 'idlelib.PyShell':
Walter Dörwald70a6b492004-02-12 17:35:32 +0000377 command = "__import__('idlelib.run').run.main(%r)" % (del_exitf,)
Tony Lowndsf2324b92002-09-29 00:34:10 +0000378 else:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000379 command = "__import__('run').main(%r)" % (del_exitf,)
Ned Deilye5cad232011-08-02 18:47:13 -0700380 return [sys.executable] + w + ["-c", command, str(self.port)]
Tony Lowndsf2324b92002-09-29 00:34:10 +0000381
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000382 def start_subprocess(self):
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000383 addr = (HOST, self.port)
384 # GUI makes several attempts to acquire socket, listens for connection
Kurt B. Kaiser5db48432003-05-15 03:40:51 +0000385 for i in range(3):
Chui Tey5d2af632002-05-26 13:36:41 +0000386 time.sleep(i)
387 try:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000388 self.rpcclt = MyRPCClient(addr)
Chui Tey5d2af632002-05-26 13:36:41 +0000389 break
Guido van Rossumb940e112007-01-10 16:19:56 +0000390 except socket.error as err:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000391 pass
Chui Tey5d2af632002-05-26 13:36:41 +0000392 else:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000393 self.display_port_binding_error()
394 return None
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000395 # if PORT was 0, system will assign an 'ephemeral' port. Find it out:
396 self.port = self.rpcclt.listening_sock.getsockname()[1]
397 # if PORT was not 0, probably working with a remote execution server
398 if PORT != 0:
399 # To allow reconnection within the 2MSL wait (cf. Stevens TCP
400 # V1, 18.6), set SO_REUSEADDR. Note that this can be problematic
401 # on Windows since the implementation allows two active sockets on
402 # the same address!
403 self.rpcclt.listening_sock.setsockopt(socket.SOL_SOCKET,
404 socket.SO_REUSEADDR, 1)
405 self.spawn_subprocess()
406 #time.sleep(20) # test to simulate GUI not accepting connection
Kurt B. Kaiserb4179362002-07-26 00:06:42 +0000407 # Accept the connection from the Python execution server
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000408 self.rpcclt.listening_sock.settimeout(10)
409 try:
410 self.rpcclt.accept()
Guido van Rossumb940e112007-01-10 16:19:56 +0000411 except socket.timeout as err:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000412 self.display_no_subprocess_error()
413 return None
Martin v. Löwisc882b7c2012-07-25 10:47:20 +0200414 # Can't regiter self.tkconsole.stdin, since run.py wants to
415 # call non-TextIO methods on it (such as getvar)
416 # XXX should be renamed to "console"
Kurt B. Kaiser969de452002-06-12 03:28:57 +0000417 self.rpcclt.register("stdin", self.tkconsole)
418 self.rpcclt.register("stdout", self.tkconsole.stdout)
419 self.rpcclt.register("stderr", self.tkconsole.stderr)
Chui Tey5d2af632002-05-26 13:36:41 +0000420 self.rpcclt.register("flist", self.tkconsole.flist)
Kurt B. Kaiser8cd0def2003-01-31 05:06:43 +0000421 self.rpcclt.register("linecache", linecache)
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000422 self.rpcclt.register("interp", self)
Terry Jan Reedyda4c4672012-01-31 02:26:32 -0500423 self.transfer_path(with_cwd=True)
Chui Tey5d2af632002-05-26 13:36:41 +0000424 self.poll_subprocess()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000425 return self.rpcclt
Chui Tey5d2af632002-05-26 13:36:41 +0000426
Terry Jan Reedyda4c4672012-01-31 02:26:32 -0500427 def restart_subprocess(self, with_cwd=False):
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000428 if self.restarting:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000429 return self.rpcclt
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000430 self.restarting = True
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000431 # close only the subprocess debugger
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000432 debug = self.getdebugger()
433 if debug:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000434 try:
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000435 # Only close subprocess debugger, don't unregister gui_adap!
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000436 RemoteDebugger.close_subprocess_debugger(self.rpcclt)
437 except:
438 pass
439 # Kill subprocess, spawn a new one, accept connection.
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000440 self.rpcclt.close()
Ned Deilye5cad232011-08-02 18:47:13 -0700441 self.terminate_subprocess()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000442 console = self.tkconsole
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000443 was_executing = console.executing
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000444 console.executing = False
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000445 self.spawn_subprocess()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000446 try:
447 self.rpcclt.accept()
Guido van Rossumb940e112007-01-10 16:19:56 +0000448 except socket.timeout as err:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000449 self.display_no_subprocess_error()
450 return None
Terry Jan Reedyda4c4672012-01-31 02:26:32 -0500451 self.transfer_path(with_cwd=with_cwd)
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000452 # annotate restart in shell window and mark it
Kurt B. Kaiser4cc5ef52003-01-22 00:23:23 +0000453 console.text.delete("iomark", "end-1c")
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000454 if was_executing:
455 console.write('\n')
456 console.showprompt()
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000457 halfbar = ((int(console.width) - 16) // 2) * '='
458 console.write(halfbar + ' RESTART ' + halfbar)
459 console.text.mark_set("restart", "end-1c")
460 console.text.mark_gravity("restart", "left")
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000461 console.showprompt()
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000462 # restart subprocess debugger
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000463 if debug:
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000464 # Restarted debugger connects to current instance of debug GUI
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000465 gui = RemoteDebugger.restart_subprocess_debugger(self.rpcclt)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000466 # reload remote debugger breakpoints for all PyShellEditWindows
467 debug.load_breakpoints()
Ned Deily7aff4512011-10-30 20:01:35 -0700468 self.compile.compiler.flags = self.original_compiler_flags
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000469 self.restarting = False
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000470 return self.rpcclt
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000471
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000472 def __request_interrupt(self):
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000473 self.rpcclt.remotecall("exec", "interrupt_the_server", (), {})
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000474
475 def interrupt_subprocess(self):
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000476 threading.Thread(target=self.__request_interrupt).start()
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000477
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000478 def kill_subprocess(self):
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000479 try:
480 self.rpcclt.close()
481 except AttributeError: # no socket
482 pass
Ned Deilye5cad232011-08-02 18:47:13 -0700483 self.terminate_subprocess()
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000484 self.tkconsole.executing = False
485 self.rpcclt = None
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000486
Ned Deilye5cad232011-08-02 18:47:13 -0700487 def terminate_subprocess(self):
488 "Make sure subprocess is terminated"
489 try:
490 self.rpcsubproc.kill()
491 except OSError:
492 # process already terminated
493 return
494 else:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000495 try:
Ned Deilye5cad232011-08-02 18:47:13 -0700496 self.rpcsubproc.wait()
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000497 except OSError:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000498 return
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000499
Terry Jan Reedyda4c4672012-01-31 02:26:32 -0500500 def transfer_path(self, with_cwd=False):
501 if with_cwd: # Issue 13506
502 path = [''] # include Current Working Directory
503 path.extend(sys.path)
504 else:
505 path = sys.path
Terry Jan Reedy4d82ade2012-01-31 02:57:29 -0500506
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000507 self.runcommand("""if 1:
508 import sys as _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +0000509 _sys.path = %r
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000510 del _sys
Terry Jan Reedyda4c4672012-01-31 02:26:32 -0500511 \n""" % (path,))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000512
Chui Tey5d2af632002-05-26 13:36:41 +0000513 active_seq = None
514
515 def poll_subprocess(self):
516 clt = self.rpcclt
517 if clt is None:
518 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000519 try:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000520 response = clt.pollresponse(self.active_seq, wait=0.05)
521 except (EOFError, IOError, KeyboardInterrupt):
522 # lost connection or subprocess terminated itself, restart
523 # [the KBI is from rpc.SocketIO.handle_EOF()]
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000524 if self.tkconsole.closing:
525 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000526 response = None
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000527 self.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000528 if response:
529 self.tkconsole.resetoutput()
530 self.active_seq = None
531 how, what = response
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000532 console = self.tkconsole.console
Chui Tey5d2af632002-05-26 13:36:41 +0000533 if how == "OK":
534 if what is not None:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000535 print(repr(what), file=console)
Chui Tey5d2af632002-05-26 13:36:41 +0000536 elif how == "EXCEPTION":
Chui Tey5d2af632002-05-26 13:36:41 +0000537 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
538 self.remote_stack_viewer()
539 elif how == "ERROR":
Kurt B. Kaiser0930c432002-12-06 21:45:24 +0000540 errmsg = "PyShell.ModifiedInterpreter: Subprocess ERROR:\n"
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000541 print(errmsg, what, file=sys.__stderr__)
542 print(errmsg, what, file=console)
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000543 # we received a response to the currently active seq number:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000544 try:
545 self.tkconsole.endexecuting()
546 except AttributeError: # shell may have closed
547 pass
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000548 # Reschedule myself
549 if not self.tkconsole.closing:
550 self.tkconsole.text.after(self.tkconsole.pollinterval,
551 self.poll_subprocess)
Chui Tey5d2af632002-05-26 13:36:41 +0000552
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000553 debugger = None
554
555 def setdebugger(self, debugger):
556 self.debugger = debugger
557
558 def getdebugger(self):
559 return self.debugger
560
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000561 def open_remote_stack_viewer(self):
562 """Initiate the remote stack viewer from a separate thread.
563
564 This method is called from the subprocess, and by returning from this
565 method we allow the subprocess to unblock. After a bit the shell
566 requests the subprocess to open the remote stack viewer which returns a
Ezio Melotti60861182010-07-23 16:48:22 +0000567 static object looking at the last exception. It is queried through
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000568 the RPC mechanism.
569
570 """
571 self.tkconsole.text.after(300, self.remote_stack_viewer)
572 return
573
Chui Tey5d2af632002-05-26 13:36:41 +0000574 def remote_stack_viewer(self):
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000575 from idlelib import RemoteObjectBrowser
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000576 oid = self.rpcclt.remotequeue("exec", "stackviewer", ("flist",), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000577 if oid is None:
578 self.tkconsole.root.bell()
579 return
580 item = RemoteObjectBrowser.StubObjectTreeItem(self.rpcclt, oid)
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000581 from idlelib.TreeWidget import ScrolledCanvas, TreeNode
Chui Tey5d2af632002-05-26 13:36:41 +0000582 top = Toplevel(self.tkconsole.root)
Kurt B. Kaiser73360a32004-03-08 18:15:31 +0000583 theme = idleConf.GetOption('main','Theme','name')
584 background = idleConf.GetHighlight(theme, 'normal')['background']
585 sc = ScrolledCanvas(top, bg=background, highlightthickness=0)
Chui Tey5d2af632002-05-26 13:36:41 +0000586 sc.frame.pack(expand=1, fill="both")
587 node = TreeNode(sc.canvas, None, item)
588 node.expand()
589 # XXX Should GC the remote tree when closing the window
590
David Scherer7aced172000-08-15 01:13:23 +0000591 gid = 0
592
593 def execsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000594 "Like runsource() but assumes complete exec source"
David Scherer7aced172000-08-15 01:13:23 +0000595 filename = self.stuffsource(source)
596 self.execfile(filename, source)
597
598 def execfile(self, filename, source=None):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000599 "Execute an existing file"
David Scherer7aced172000-08-15 01:13:23 +0000600 if source is None:
Victor Stinner979482a2011-09-02 01:00:40 +0200601 with tokenize.open(filename) as fp:
Victor Stinner85c67722011-09-02 00:57:04 +0200602 source = fp.read()
David Scherer7aced172000-08-15 01:13:23 +0000603 try:
604 code = compile(source, filename, "exec")
605 except (OverflowError, SyntaxError):
606 self.tkconsole.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000607 tkerr = self.tkconsole.stderr
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000608 print('*** Error in script or command!\n', file=tkerr)
609 print('Traceback (most recent call last):', file=tkerr)
David Scherer7aced172000-08-15 01:13:23 +0000610 InteractiveInterpreter.showsyntaxerror(self, filename)
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000611 self.tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000612 else:
613 self.runcode(code)
614
615 def runsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000616 "Extend base class method: Stuff the source in the line cache first"
David Scherer7aced172000-08-15 01:13:23 +0000617 filename = self.stuffsource(source)
618 self.more = 0
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000619 self.save_warnings_filters = warnings.filters[:]
620 warnings.filterwarnings(action="error", category=SyntaxWarning)
Martin v. Löwis98ff8982007-08-13 06:03:15 +0000621 # at the moment, InteractiveInterpreter expects str
622 assert isinstance(source, str)
623 #if isinstance(source, str):
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000624 # from idlelib import IOBinding
Martin v. Löwis98ff8982007-08-13 06:03:15 +0000625 # try:
626 # source = source.encode(IOBinding.encoding)
627 # except UnicodeError:
628 # self.tkconsole.resetoutput()
629 # self.write("Unsupported characters in input\n")
630 # return
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000631 try:
Kurt B. Kaiser935ea9a2005-05-10 03:44:24 +0000632 # InteractiveInterpreter.runsource() calls its runcode() method,
633 # which is overridden (see below)
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000634 return InteractiveInterpreter.runsource(self, source, filename)
635 finally:
636 if self.save_warnings_filters is not None:
637 warnings.filters[:] = self.save_warnings_filters
638 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000639
640 def stuffsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000641 "Stuff source in the filename cache"
David Scherer7aced172000-08-15 01:13:23 +0000642 filename = "<pyshell#%d>" % self.gid
643 self.gid = self.gid + 1
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000644 lines = source.split("\n")
David Scherer7aced172000-08-15 01:13:23 +0000645 linecache.cache[filename] = len(source)+1, 0, lines, filename
646 return filename
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000647
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000648 def prepend_syspath(self, filename):
649 "Prepend sys.path with file's directory if not already included"
650 self.runcommand("""if 1:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000651 _filename = %r
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000652 import sys as _sys
653 from os.path import dirname as _dirname
654 _dir = _dirname(_filename)
655 if not _dir in _sys.path:
656 _sys.path.insert(0, _dir)
657 del _filename, _sys, _dirname, _dir
Walter Dörwald70a6b492004-02-12 17:35:32 +0000658 \n""" % (filename,))
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000659
David Scherer7aced172000-08-15 01:13:23 +0000660 def showsyntaxerror(self, filename=None):
Guido van Rossum33d26892007-08-05 15:29:28 +0000661 """Override Interactive Interpreter method: Use Colorizing
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000662
663 Color the offending position instead of printing it and pointing at it
664 with a caret.
665
666 """
Guido van Rossum33d26892007-08-05 15:29:28 +0000667 tkconsole = self.tkconsole
668 text = tkconsole.text
669 text.tag_remove("ERROR", "1.0", "end")
David Scherer7aced172000-08-15 01:13:23 +0000670 type, value, tb = sys.exc_info()
Ned Deily79746422011-09-14 14:49:14 -0700671 msg = getattr(value, 'msg', '') or value or "<no detail available>"
672 lineno = getattr(value, 'lineno', '') or 1
673 offset = getattr(value, 'offset', '') or 0
Guido van Rossum33d26892007-08-05 15:29:28 +0000674 if offset == 0:
675 lineno += 1 #mark end of offending line
676 if lineno == 1:
677 pos = "iomark + %d chars" % (offset-1)
David Scherer7aced172000-08-15 01:13:23 +0000678 else:
Guido van Rossum33d26892007-08-05 15:29:28 +0000679 pos = "iomark linestart + %d lines + %d chars" % \
680 (lineno-1, offset-1)
681 tkconsole.colorize_syntax_error(text, pos)
682 tkconsole.resetoutput()
683 self.write("SyntaxError: %s\n" % msg)
684 tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000685
686 def showtraceback(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000687 "Extend base class method to reset output properly"
David Scherer7aced172000-08-15 01:13:23 +0000688 self.tkconsole.resetoutput()
689 self.checklinecache()
690 InteractiveInterpreter.showtraceback(self)
Chui Tey5d2af632002-05-26 13:36:41 +0000691 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
692 self.tkconsole.open_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +0000693
694 def checklinecache(self):
695 c = linecache.cache
Guido van Rossum36e0a922007-07-20 04:05:57 +0000696 for key in list(c.keys()):
David Scherer7aced172000-08-15 01:13:23 +0000697 if key[:1] + key[-1:] != "<>":
698 del c[key]
699
Chui Tey5d2af632002-05-26 13:36:41 +0000700 def runcommand(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000701 "Run the code without invoking the debugger"
Chui Tey5d2af632002-05-26 13:36:41 +0000702 # The code better not raise an exception!
703 if self.tkconsole.executing:
Neal Norwitzf4c4f112002-11-30 18:49:10 +0000704 self.display_executing_dialog()
Chui Tey5d2af632002-05-26 13:36:41 +0000705 return 0
706 if self.rpcclt:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000707 self.rpcclt.remotequeue("exec", "runcode", (code,), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000708 else:
Georg Brandl7cae87c2006-09-06 06:51:57 +0000709 exec(code, self.locals)
Chui Tey5d2af632002-05-26 13:36:41 +0000710 return 1
711
David Scherer7aced172000-08-15 01:13:23 +0000712 def runcode(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000713 "Override base class method"
Chui Tey5d2af632002-05-26 13:36:41 +0000714 if self.tkconsole.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000715 self.interp.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000716 self.checklinecache()
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000717 if self.save_warnings_filters is not None:
718 warnings.filters[:] = self.save_warnings_filters
719 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000720 debugger = self.debugger
721 try:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000722 self.tkconsole.beginexecuting()
Thomas Wouterscf297e42007-02-23 15:07:44 +0000723 if not debugger and self.rpcclt is not None:
724 self.active_seq = self.rpcclt.asyncqueue("exec", "runcode",
725 (code,), {})
726 elif debugger:
727 debugger.run(code, self.locals)
728 else:
729 exec(code, self.locals)
730 except SystemExit:
731 if not self.tkconsole.closing:
732 if tkMessageBox.askyesno(
733 "Exit?",
734 "Do you want to exit altogether?",
735 default="yes",
736 master=self.tkconsole.text):
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000737 raise
Thomas Wouterscf297e42007-02-23 15:07:44 +0000738 else:
Guido van Rossum5dc0d972007-02-25 22:37:36 +0000739 self.showtraceback()
Thomas Wouterscf297e42007-02-23 15:07:44 +0000740 else:
741 raise
742 except:
743 if use_subprocess:
744 print("IDLE internal error in runcode()",
745 file=self.tkconsole.stderr)
David Scherer7aced172000-08-15 01:13:23 +0000746 self.showtraceback()
Thomas Wouterscf297e42007-02-23 15:07:44 +0000747 self.tkconsole.endexecuting()
748 else:
749 if self.tkconsole.canceled:
750 self.tkconsole.canceled = False
751 print("KeyboardInterrupt", file=self.tkconsole.stderr)
752 else:
753 self.showtraceback()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000754 finally:
755 if not use_subprocess:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000756 try:
757 self.tkconsole.endexecuting()
758 except AttributeError: # shell may have closed
759 pass
David Scherer7aced172000-08-15 01:13:23 +0000760
761 def write(self, s):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000762 "Override base class method"
Martin v. Löwis30d5e6c2012-07-25 11:32:26 +0200763 return self.tkconsole.stderr.write(s)
David Scherer7aced172000-08-15 01:13:23 +0000764
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000765 def display_port_binding_error(self):
766 tkMessageBox.showerror(
767 "Port Binding Error",
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000768 "IDLE can't bind to a TCP/IP port, which is necessary to "
769 "communicate with its Python execution server. This might be "
770 "because no networking is installed on this computer. "
771 "Run IDLE with the -n command line switch to start without a "
772 "subprocess and refer to Help/IDLE Help 'Running without a "
773 "subprocess' for further details.",
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000774 master=self.tkconsole.text)
775
776 def display_no_subprocess_error(self):
777 tkMessageBox.showerror(
778 "Subprocess Startup Error",
779 "IDLE's subprocess didn't make connection. Either IDLE can't "
780 "start a subprocess or personal firewall software is blocking "
781 "the connection.",
782 master=self.tkconsole.text)
783
784 def display_executing_dialog(self):
785 tkMessageBox.showerror(
786 "Already executing",
787 "The Python Shell window is already executing a command; "
788 "please wait until it is finished.",
789 master=self.tkconsole.text)
790
791
David Scherer7aced172000-08-15 01:13:23 +0000792class PyShell(OutputWindow):
793
794 shell_title = "Python Shell"
795
796 # Override classes
797 ColorDelegator = ModifiedColorDelegator
798 UndoDelegator = ModifiedUndoDelegator
799
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000800 # Override menus
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000801 menu_specs = [
802 ("file", "_File"),
803 ("edit", "_Edit"),
Kurt B. Kaiser4cc5ef52003-01-22 00:23:23 +0000804 ("debug", "_Debug"),
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000805 ("options", "_Options"),
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000806 ("windows", "_Windows"),
807 ("help", "_Help"),
808 ]
David Scherer7aced172000-08-15 01:13:23 +0000809
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000810 if macosxSupport.runningAsOSXApp():
811 del menu_specs[-3]
812 menu_specs[-2] = ("windows", "_Window")
813
814
David Scherer7aced172000-08-15 01:13:23 +0000815 # New classes
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000816 from idlelib.IdleHistory import History
David Scherer7aced172000-08-15 01:13:23 +0000817
818 def __init__(self, flist=None):
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000819 if use_subprocess:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000820 ms = self.menu_specs
821 if ms[2][0] != "shell":
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000822 ms.insert(2, ("shell", "She_ll"))
David Scherer7aced172000-08-15 01:13:23 +0000823 self.interp = ModifiedInterpreter(self)
824 if flist is None:
825 root = Tk()
826 fixwordbreaks(root)
827 root.withdraw()
828 flist = PyShellFileList(root)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000829 #
David Scherer7aced172000-08-15 01:13:23 +0000830 OutputWindow.__init__(self, flist, None, None)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000831 #
Kurt B. Kaiser6af44982005-01-19 00:22:59 +0000832## self.config(usetabs=1, indentwidth=8, context_use_ps1=1)
833 self.usetabs = True
834 # indentwidth must be 8 when using tabs. See note in EditorWindow:
835 self.indentwidth = 8
836 self.context_use_ps1 = True
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000837 #
David Scherer7aced172000-08-15 01:13:23 +0000838 text = self.text
839 text.configure(wrap="char")
840 text.bind("<<newline-and-indent>>", self.enter_callback)
841 text.bind("<<plain-newline-and-indent>>", self.linefeed_callback)
842 text.bind("<<interrupt-execution>>", self.cancel_callback)
David Scherer7aced172000-08-15 01:13:23 +0000843 text.bind("<<end-of-file>>", self.eof_callback)
844 text.bind("<<open-stack-viewer>>", self.open_stack_viewer)
Kurt B. Kaiser57bfe5d2003-05-10 00:09:52 +0000845 text.bind("<<toggle-debugger>>", self.toggle_debugger)
David Scherer7aced172000-08-15 01:13:23 +0000846 text.bind("<<toggle-jit-stack-viewer>>", self.toggle_jit_stack_viewer)
Kurt B. Kaiser8a78cad2007-12-13 03:38:16 +0000847 self.color = color = self.ColorDelegator()
848 self.per.insertfilter(color)
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000849 if use_subprocess:
850 text.bind("<<view-restart>>", self.view_restart_mark)
851 text.bind("<<restart-shell>>", self.restart_shell)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000852 #
David Scherer7aced172000-08-15 01:13:23 +0000853 self.save_stdout = sys.stdout
854 self.save_stderr = sys.stderr
855 self.save_stdin = sys.stdin
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000856 from idlelib import IOBinding
Martin v. Löwisc882b7c2012-07-25 10:47:20 +0200857 self.stdin = PseudoInputFile(self)
Martin v. Löwisbcc651a2003-06-22 07:52:56 +0000858 self.stdout = PseudoFile(self, "stdout", IOBinding.encoding)
859 self.stderr = PseudoFile(self, "stderr", IOBinding.encoding)
860 self.console = PseudoFile(self, "console", IOBinding.encoding)
Chui Tey5d2af632002-05-26 13:36:41 +0000861 if not use_subprocess:
862 sys.stdout = self.stdout
Kurt B. Kaiser7cec2522007-08-31 04:15:13 +0000863 sys.stderr = self.stderr
Martin v. Löwisc882b7c2012-07-25 10:47:20 +0200864 sys.stdin = self.stdin
Kurt B. Kaiserf609a342007-12-28 03:57:56 +0000865 try:
866 # page help() text to shell.
867 import pydoc # import must be done here to capture i/o rebinding.
868 # XXX KBK 27Dec07 use a textView someday, but must work w/o subproc
869 pydoc.pager = pydoc.plainpager
870 except:
871 sys.stderr = sys.__stderr__
872 raise
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000873 #
David Scherer7aced172000-08-15 01:13:23 +0000874 self.history = self.History(self.text)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000875 #
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000876 self.pollinterval = 50 # millisec
Chui Tey5d2af632002-05-26 13:36:41 +0000877
Kurt B. Kaiser4d5bc602004-06-06 01:29:22 +0000878 def get_standard_extension_names(self):
879 return idleConf.GetExtensions(shell_only=True)
880
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000881 reading = False
882 executing = False
883 canceled = False
884 endoffile = False
885 closing = False
David Scherer7aced172000-08-15 01:13:23 +0000886
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +0000887 def set_warning_stream(self, stream):
Skip Montanarod9161422004-07-06 21:53:27 +0000888 global warning_stream
889 warning_stream = stream
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +0000890
891 def get_warning_stream(self):
892 return warning_stream
893
David Scherer7aced172000-08-15 01:13:23 +0000894 def toggle_debugger(self, event=None):
895 if self.executing:
896 tkMessageBox.showerror("Don't debug now",
897 "You can only toggle the debugger when idle",
898 master=self.text)
899 self.set_debugger_indicator()
900 return "break"
901 else:
902 db = self.interp.getdebugger()
903 if db:
904 self.close_debugger()
905 else:
906 self.open_debugger()
907
908 def set_debugger_indicator(self):
909 db = self.interp.getdebugger()
910 self.setvar("<<toggle-debugger>>", not not db)
911
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000912 def toggle_jit_stack_viewer(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +0000913 pass # All we need is the variable
914
915 def close_debugger(self):
916 db = self.interp.getdebugger()
917 if db:
918 self.interp.setdebugger(None)
919 db.close()
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000920 if self.interp.rpcclt:
921 RemoteDebugger.close_remote_debugger(self.interp.rpcclt)
David Scherer7aced172000-08-15 01:13:23 +0000922 self.resetoutput()
923 self.console.write("[DEBUG OFF]\n")
924 sys.ps1 = ">>> "
925 self.showprompt()
926 self.set_debugger_indicator()
927
928 def open_debugger(self):
Chui Tey5d2af632002-05-26 13:36:41 +0000929 if self.interp.rpcclt:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000930 dbg_gui = RemoteDebugger.start_remote_debugger(self.interp.rpcclt,
931 self)
932 else:
933 dbg_gui = Debugger.Debugger(self)
934 self.interp.setdebugger(dbg_gui)
935 dbg_gui.load_breakpoints()
Chui Tey5d2af632002-05-26 13:36:41 +0000936 sys.ps1 = "[DEBUG ON]\n>>> "
937 self.showprompt()
938 self.set_debugger_indicator()
939
David Scherer7aced172000-08-15 01:13:23 +0000940 def beginexecuting(self):
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000941 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +0000942 self.resetoutput()
943 self.executing = 1
David Scherer7aced172000-08-15 01:13:23 +0000944
945 def endexecuting(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000946 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +0000947 self.executing = 0
948 self.canceled = 0
Chui Tey5d2af632002-05-26 13:36:41 +0000949 self.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000950
951 def close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000952 "Extend EditorWindow.close()"
David Scherer7aced172000-08-15 01:13:23 +0000953 if self.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000954 response = tkMessageBox.askokcancel(
David Scherer7aced172000-08-15 01:13:23 +0000955 "Kill?",
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000956 "The program is still running!\n Do you want to kill it?",
David Scherer7aced172000-08-15 01:13:23 +0000957 default="ok",
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000958 parent=self.text)
Benjamin Peterson2a691a82008-03-31 01:51:45 +0000959 if response is False:
David Scherer7aced172000-08-15 01:13:23 +0000960 return "cancel"
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +0000961 if self.reading:
962 self.top.quit()
963 self.canceled = True
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000964 self.closing = True
965 # Wait for poll_subprocess() rescheduling to stop
966 self.text.after(2 * self.pollinterval, self.close2)
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000967
968 def close2(self):
969 return EditorWindow.close(self)
David Scherer7aced172000-08-15 01:13:23 +0000970
971 def _close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000972 "Extend EditorWindow._close(), shut down debugger and execution server"
David Scherer7aced172000-08-15 01:13:23 +0000973 self.close_debugger()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000974 if use_subprocess:
975 self.interp.kill_subprocess()
David Scherer7aced172000-08-15 01:13:23 +0000976 # Restore std streams
977 sys.stdout = self.save_stdout
978 sys.stderr = self.save_stderr
979 sys.stdin = self.save_stdin
980 # Break cycles
981 self.interp = None
982 self.console = None
David Scherer7aced172000-08-15 01:13:23 +0000983 self.flist.pyshell = None
984 self.history = None
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000985 EditorWindow._close(self)
David Scherer7aced172000-08-15 01:13:23 +0000986
987 def ispythonsource(self, filename):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000988 "Override EditorWindow method: never remove the colorizer"
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000989 return True
David Scherer7aced172000-08-15 01:13:23 +0000990
991 def short_title(self):
992 return self.shell_title
993
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000994 COPYRIGHT = \
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000995 'Type "copyright", "credits" or "license()" for more information.'
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000996
David Scherer7aced172000-08-15 01:13:23 +0000997 def begin(self):
Kurt B. Kaiser7378df72007-08-11 04:20:51 +0000998 self.text.mark_set("iomark", "insert")
David Scherer7aced172000-08-15 01:13:23 +0000999 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001000 if use_subprocess:
1001 nosub = ''
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001002 client = self.interp.start_subprocess()
1003 if not client:
1004 self.close()
Kurt B. Kaiser76637292004-01-21 22:10:01 +00001005 return False
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001006 else:
1007 nosub = "==== No Subprocess ===="
Raymond Hettingera2a8e8b2009-01-27 00:28:36 +00001008 self.write("Python %s on %s\n%s\n%s" %
1009 (sys.version, sys.platform, self.COPYRIGHT, nosub))
David Scherer7aced172000-08-15 01:13:23 +00001010 self.showprompt()
Georg Brandl14fc4272008-05-17 18:39:55 +00001011 import tkinter
1012 tkinter._default_root = None # 03Jan04 KBK What's this?
Kurt B. Kaiser76637292004-01-21 22:10:01 +00001013 return True
David Scherer7aced172000-08-15 01:13:23 +00001014
1015 def readline(self):
1016 save = self.reading
1017 try:
1018 self.reading = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001019 self.top.mainloop() # nested mainloop()
David Scherer7aced172000-08-15 01:13:23 +00001020 finally:
1021 self.reading = save
1022 line = self.text.get("iomark", "end-1c")
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001023 if len(line) == 0: # may be EOF if we quit our mainloop with Ctrl-C
1024 line = "\n"
David Scherer7aced172000-08-15 01:13:23 +00001025 self.resetoutput()
1026 if self.canceled:
1027 self.canceled = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001028 if not use_subprocess:
1029 raise KeyboardInterrupt
David Scherer7aced172000-08-15 01:13:23 +00001030 if self.endoffile:
1031 self.endoffile = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001032 line = ""
David Scherer7aced172000-08-15 01:13:23 +00001033 return line
1034
1035 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001036 return True
David Scherer7aced172000-08-15 01:13:23 +00001037
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001038 def cancel_callback(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +00001039 try:
1040 if self.text.compare("sel.first", "!=", "sel.last"):
1041 return # Active selection -- always use default binding
1042 except:
1043 pass
1044 if not (self.executing or self.reading):
1045 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001046 self.interp.write("KeyboardInterrupt\n")
David Scherer7aced172000-08-15 01:13:23 +00001047 self.showprompt()
1048 return "break"
1049 self.endoffile = 0
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001050 self.canceled = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001051 if (self.executing and self.interp.rpcclt):
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +00001052 if self.interp.getdebugger():
1053 self.interp.restart_subprocess()
1054 else:
1055 self.interp.interrupt_subprocess()
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001056 if self.reading:
1057 self.top.quit() # exit the nested mainloop() in readline()
David Scherer7aced172000-08-15 01:13:23 +00001058 return "break"
1059
1060 def eof_callback(self, event):
1061 if self.executing and not self.reading:
1062 return # Let the default binding (delete next char) take over
1063 if not (self.text.compare("iomark", "==", "insert") and
1064 self.text.compare("insert", "==", "end-1c")):
1065 return # Let the default binding (delete next char) take over
1066 if not self.executing:
David Scherer7aced172000-08-15 01:13:23 +00001067 self.resetoutput()
1068 self.close()
1069 else:
1070 self.canceled = 0
1071 self.endoffile = 1
1072 self.top.quit()
1073 return "break"
1074
David Scherer7aced172000-08-15 01:13:23 +00001075 def linefeed_callback(self, event):
1076 # Insert a linefeed without entering anything (still autoindented)
1077 if self.reading:
1078 self.text.insert("insert", "\n")
1079 self.text.see("insert")
1080 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001081 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001082 return "break"
1083
1084 def enter_callback(self, event):
1085 if self.executing and not self.reading:
1086 return # Let the default binding (insert '\n') take over
1087 # If some text is selected, recall the selection
1088 # (but only if this before the I/O mark)
1089 try:
1090 sel = self.text.get("sel.first", "sel.last")
1091 if sel:
1092 if self.text.compare("sel.last", "<=", "iomark"):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001093 self.recall(sel, event)
David Scherer7aced172000-08-15 01:13:23 +00001094 return "break"
1095 except:
1096 pass
1097 # If we're strictly before the line containing iomark, recall
1098 # the current line, less a leading prompt, less leading or
1099 # trailing whitespace
1100 if self.text.compare("insert", "<", "iomark linestart"):
1101 # Check if there's a relevant stdin range -- if so, use it
1102 prev = self.text.tag_prevrange("stdin", "insert")
1103 if prev and self.text.compare("insert", "<", prev[1]):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001104 self.recall(self.text.get(prev[0], prev[1]), event)
David Scherer7aced172000-08-15 01:13:23 +00001105 return "break"
1106 next = self.text.tag_nextrange("stdin", "insert")
1107 if next and self.text.compare("insert lineend", ">=", next[0]):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001108 self.recall(self.text.get(next[0], next[1]), event)
David Scherer7aced172000-08-15 01:13:23 +00001109 return "break"
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001110 # No stdin mark -- just get the current line, less any prompt
Kurt B. Kaiserb1754452005-11-18 22:05:48 +00001111 indices = self.text.tag_nextrange("console", "insert linestart")
1112 if indices and \
1113 self.text.compare(indices[0], "<=", "insert linestart"):
1114 self.recall(self.text.get(indices[1], "insert lineend"), event)
1115 else:
1116 self.recall(self.text.get("insert linestart", "insert lineend"), event)
David Scherer7aced172000-08-15 01:13:23 +00001117 return "break"
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001118 # If we're between the beginning of the line and the iomark, i.e.
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001119 # in the prompt area, move to the end of the prompt
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001120 if self.text.compare("insert", "<", "iomark"):
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001121 self.text.mark_set("insert", "iomark")
David Scherer7aced172000-08-15 01:13:23 +00001122 # If we're in the current input and there's only whitespace
1123 # beyond the cursor, erase that whitespace first
1124 s = self.text.get("insert", "end-1c")
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001125 if s and not s.strip():
David Scherer7aced172000-08-15 01:13:23 +00001126 self.text.delete("insert", "end-1c")
1127 # If we're in the current input before its last line,
1128 # insert a newline right at the insert point
1129 if self.text.compare("insert", "<", "end-1c linestart"):
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001130 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001131 return "break"
1132 # We're in the last line; append a newline and submit it
1133 self.text.mark_set("insert", "end-1c")
1134 if self.reading:
1135 self.text.insert("insert", "\n")
1136 self.text.see("insert")
1137 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001138 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001139 self.text.tag_add("stdin", "iomark", "end-1c")
1140 self.text.update_idletasks()
1141 if self.reading:
Neal Norwitzce96f692006-03-17 06:49:51 +00001142 self.top.quit() # Break out of recursive mainloop()
David Scherer7aced172000-08-15 01:13:23 +00001143 else:
1144 self.runit()
1145 return "break"
1146
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001147 def recall(self, s, event):
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001148 # remove leading and trailing empty or whitespace lines
1149 s = re.sub(r'^\s*\n', '' , s)
1150 s = re.sub(r'\n\s*$', '', s)
1151 lines = s.split('\n')
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001152 self.text.undo_block_start()
1153 try:
1154 self.text.tag_remove("sel", "1.0", "end")
1155 self.text.mark_set("insert", "end-1c")
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001156 prefix = self.text.get("insert linestart", "insert")
1157 if prefix.rstrip().endswith(':'):
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001158 self.newline_and_indent_event(event)
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001159 prefix = self.text.get("insert linestart", "insert")
1160 self.text.insert("insert", lines[0].strip())
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001161 if len(lines) > 1:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001162 orig_base_indent = re.search(r'^([ \t]*)', lines[0]).group(0)
1163 new_base_indent = re.search(r'^([ \t]*)', prefix).group(0)
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001164 for line in lines[1:]:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001165 if line.startswith(orig_base_indent):
1166 # replace orig base indentation with new indentation
1167 line = new_base_indent + line[len(orig_base_indent):]
1168 self.text.insert('insert', '\n'+line.rstrip())
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001169 finally:
1170 self.text.see("insert")
1171 self.text.undo_block_stop()
David Scherer7aced172000-08-15 01:13:23 +00001172
1173 def runit(self):
1174 line = self.text.get("iomark", "end-1c")
1175 # Strip off last newline and surrounding whitespace.
1176 # (To allow you to hit return twice to end a statement.)
1177 i = len(line)
1178 while i > 0 and line[i-1] in " \t":
1179 i = i-1
1180 if i > 0 and line[i-1] == "\n":
1181 i = i-1
1182 while i > 0 and line[i-1] in " \t":
1183 i = i-1
1184 line = line[:i]
1185 more = self.interp.runsource(line)
David Scherer7aced172000-08-15 01:13:23 +00001186
David Scherer7aced172000-08-15 01:13:23 +00001187 def open_stack_viewer(self, event=None):
Chui Tey5d2af632002-05-26 13:36:41 +00001188 if self.interp.rpcclt:
1189 return self.interp.remote_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +00001190 try:
1191 sys.last_traceback
1192 except:
1193 tkMessageBox.showerror("No stack trace",
1194 "There is no stack trace yet.\n"
1195 "(sys.last_traceback is not defined)",
1196 master=self.text)
1197 return
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +00001198 from idlelib.StackViewer import StackBrowser
David Scherer7aced172000-08-15 01:13:23 +00001199 sv = StackBrowser(self.root, self.flist)
1200
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001201 def view_restart_mark(self, event=None):
1202 self.text.see("iomark")
1203 self.text.see("restart")
1204
1205 def restart_shell(self, event=None):
Terry Jan Reedyda4c4672012-01-31 02:26:32 -05001206 "Callback for Run/Restart Shell Cntl-F6"
1207 self.interp.restart_subprocess(with_cwd=True)
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001208
David Scherer7aced172000-08-15 01:13:23 +00001209 def showprompt(self):
1210 self.resetoutput()
1211 try:
1212 s = str(sys.ps1)
1213 except:
1214 s = ""
1215 self.console.write(s)
1216 self.text.mark_set("insert", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001217 self.set_line_and_column()
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +00001218 self.io.reset_undo()
David Scherer7aced172000-08-15 01:13:23 +00001219
1220 def resetoutput(self):
1221 source = self.text.get("iomark", "end-1c")
1222 if self.history:
1223 self.history.history_store(source)
1224 if self.text.get("end-2c") != "\n":
1225 self.text.insert("end-1c", "\n")
1226 self.text.mark_set("iomark", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001227 self.set_line_and_column()
David Scherer7aced172000-08-15 01:13:23 +00001228
1229 def write(self, s, tags=()):
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001230 try:
1231 self.text.mark_gravity("iomark", "right")
Martin v. Löwis30d5e6c2012-07-25 11:32:26 +02001232 count = OutputWindow.write(self, s, tags, "iomark")
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001233 self.text.mark_gravity("iomark", "left")
1234 except:
Kurt B. Kaisercbbe98f2007-08-12 01:52:35 +00001235 raise ###pass # ### 11Aug07 KBK if we are expecting exceptions
1236 # let's find out what they are and be specific.
David Scherer7aced172000-08-15 01:13:23 +00001237 if self.canceled:
1238 self.canceled = 0
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001239 if not use_subprocess:
1240 raise KeyboardInterrupt
Martin v. Löwis30d5e6c2012-07-25 11:32:26 +02001241 return count
David Scherer7aced172000-08-15 01:13:23 +00001242
Kurt B. Kaiserdcba6622004-12-21 22:10:32 +00001243class PseudoFile(object):
David Scherer7aced172000-08-15 01:13:23 +00001244
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001245 def __init__(self, shell, tags, encoding=None):
David Scherer7aced172000-08-15 01:13:23 +00001246 self.shell = shell
1247 self.tags = tags
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001248 self.encoding = encoding
David Scherer7aced172000-08-15 01:13:23 +00001249
1250 def write(self, s):
Martin v. Löwis9ae3f7a2012-07-09 20:46:11 +02001251 if not isinstance(s, str):
1252 raise TypeError('must be str, not ' + type(s).__name__)
Martin v. Löwis30d5e6c2012-07-25 11:32:26 +02001253 return self.shell.write(s, self.tags)
David Scherer7aced172000-08-15 01:13:23 +00001254
Kurt B. Kaiser66aaf742007-08-09 18:00:23 +00001255 def writelines(self, lines):
1256 for line in lines:
1257 self.write(line)
David Scherer7aced172000-08-15 01:13:23 +00001258
1259 def flush(self):
1260 pass
1261
1262 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001263 return True
David Scherer7aced172000-08-15 01:13:23 +00001264
Martin v. Löwisc882b7c2012-07-25 10:47:20 +02001265class PseudoInputFile(object):
1266 def __init__(self, shell):
1267 self.readline = shell.readline
1268 self.isatty = shell.isatty
1269
1270 def write(self, s):
1271 raise io.UnsupportedOperation("not writable")
1272 writelines = write
1273
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001274
David Scherer7aced172000-08-15 01:13:23 +00001275usage_msg = """\
David Scherer7aced172000-08-15 01:13:23 +00001276
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001277USAGE: idle [-deins] [-t title] [file]*
1278 idle [-dns] [-t title] (-c cmd | -r file) [arg]*
1279 idle [-dns] [-t title] - [arg]*
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001280
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001281 -h print this help message and exit
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001282 -n run IDLE without a subprocess (see Help/IDLE Help for details)
David Scherer7aced172000-08-15 01:13:23 +00001283
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001284The following options will override the IDLE 'settings' configuration:
Kurt B. Kaiser96d88422001-07-17 04:59:01 +00001285
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001286 -e open an edit window
1287 -i open a shell window
1288
1289The following options imply -i and will open a shell:
1290
1291 -c cmd run the command in a shell, or
1292 -r file run script from file
1293
1294 -d enable the debugger
1295 -s run $IDLESTARTUP or $PYTHONSTARTUP before anything else
1296 -t title set title of shell window
1297
1298A default edit window will be bypassed when -c, -r, or - are used.
1299
1300[arg]* are passed to the command (-c) or script (-r) in sys.argv[1:].
1301
1302Examples:
1303
1304idle
1305 Open an edit window or shell depending on IDLE's configuration.
1306
1307idle foo.py foobar.py
1308 Edit the files, also open a shell if configured to start with shell.
1309
1310idle -est "Baz" foo.py
1311 Run $IDLESTARTUP or $PYTHONSTARTUP, edit foo.py, and open a shell
1312 window with the title "Baz".
1313
Neal Norwitz752abd02008-05-13 04:55:24 +00001314idle -c "import sys; print(sys.argv)" "foo"
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001315 Open a shell window and run the command, passing "-c" in sys.argv[0]
1316 and "foo" in sys.argv[1].
1317
1318idle -d -s -r foo.py "Hello World"
1319 Open a shell window, run a startup script, enable the debugger, and
1320 run foo.py, passing "foo.py" in sys.argv[0] and "Hello World" in
1321 sys.argv[1].
1322
Neal Norwitz752abd02008-05-13 04:55:24 +00001323echo "import sys; print(sys.argv)" | idle - "foobar"
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001324 Open a shell window, run the script piped in, passing '' in sys.argv[0]
1325 and "foobar" in sys.argv[1].
David Scherer7aced172000-08-15 01:13:23 +00001326"""
1327
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001328def main():
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001329 global flist, root, use_subprocess
David Scherer7aced172000-08-15 01:13:23 +00001330
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001331 use_subprocess = True
Kurt B. Kaisere866c812009-04-04 21:07:39 +00001332 enable_shell = True
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001333 enable_edit = False
1334 debug = False
1335 cmd = None
1336 script = None
1337 startup = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001338 try:
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001339 opts, args = getopt.getopt(sys.argv[1:], "c:deihnr:st:")
Guido van Rossumb940e112007-01-10 16:19:56 +00001340 except getopt.error as msg:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001341 sys.stderr.write("Error: %s\n" % str(msg))
1342 sys.stderr.write(usage_msg)
1343 sys.exit(2)
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001344 for o, a in opts:
1345 if o == '-c':
1346 cmd = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001347 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001348 if o == '-d':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001349 debug = True
1350 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001351 if o == '-e':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001352 enable_edit = True
Kurt B. Kaisere866c812009-04-04 21:07:39 +00001353 enable_shell = False
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001354 if o == '-h':
1355 sys.stdout.write(usage_msg)
1356 sys.exit()
1357 if o == '-i':
1358 enable_shell = True
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001359 if o == '-n':
1360 use_subprocess = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001361 if o == '-r':
1362 script = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001363 if os.path.isfile(script):
1364 pass
1365 else:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001366 print("No script file: ", script)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001367 sys.exit()
1368 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001369 if o == '-s':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001370 startup = True
1371 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001372 if o == '-t':
1373 PyShell.shell_title = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001374 enable_shell = True
1375 if args and args[0] == '-':
1376 cmd = sys.stdin.read()
1377 enable_shell = True
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001378 # process sys.argv and sys.path:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001379 for i in range(len(sys.path)):
1380 sys.path[i] = os.path.abspath(sys.path[i])
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001381 if args and args[0] == '-':
1382 sys.argv = [''] + args[1:]
1383 elif cmd:
1384 sys.argv = ['-c'] + args
1385 elif script:
1386 sys.argv = [script] + args
1387 elif args:
1388 enable_edit = True
1389 pathx = []
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001390 for filename in args:
1391 pathx.append(os.path.dirname(filename))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001392 for dir in pathx:
1393 dir = os.path.abspath(dir)
1394 if not dir in sys.path:
1395 sys.path.insert(0, dir)
Kurt B. Kaiserff002b92002-12-21 21:39:11 +00001396 else:
Neal Norwitzd082b6e2007-08-26 23:37:53 +00001397 dir = os.getcwd()
1398 if dir not in sys.path:
Kurt B. Kaiserff002b92002-12-21 21:39:11 +00001399 sys.path.insert(0, dir)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001400 # check the IDLE settings configuration (but command line overrides)
1401 edit_start = idleConf.GetOption('main', 'General',
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001402 'editor-on-startup', type='bool')
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001403 enable_edit = enable_edit or edit_start
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001404 # start editor and/or shell windows:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001405 root = Tk(className="Idle")
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001406
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001407 fixwordbreaks(root)
1408 root.withdraw()
1409 flist = PyShellFileList(root)
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001410 macosxSupport.setupApp(root, flist)
1411
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001412 if enable_edit:
1413 if not (cmd or script):
Andrew Svetlov0f71f442012-03-21 13:23:41 +02001414 for filename in args[:]:
1415 if flist.open(filename) is None:
1416 # filename is a directory actually, disconsider it
1417 args.remove(filename)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001418 if not args:
1419 flist.new()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001420 if enable_shell:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001421 shell = flist.open_shell()
1422 if not shell:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001423 return # couldn't open shell
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001424
1425 if macosxSupport.runningAsOSXApp() and flist.dict:
1426 # On OSX: when the user has double-clicked on a file that causes
1427 # IDLE to be launched the shell window will open just in front of
1428 # the file she wants to see. Lower the interpreter window when
1429 # there are open files.
1430 shell.top.lower()
1431
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001432 shell = flist.pyshell
1433 # handle remaining options:
1434 if debug:
1435 shell.open_debugger()
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001436 if startup:
1437 filename = os.environ.get("IDLESTARTUP") or \
1438 os.environ.get("PYTHONSTARTUP")
1439 if filename and os.path.isfile(filename):
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001440 shell.interp.execfile(filename)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001441 if shell and cmd or script:
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001442 shell.interp.runcommand("""if 1:
1443 import sys as _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001444 _sys.argv = %r
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001445 del _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001446 \n""" % (sys.argv,))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001447 if cmd:
1448 shell.interp.execsource(cmd)
1449 elif script:
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001450 shell.interp.prepend_syspath(script)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001451 shell.interp.execfile(script)
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001452
Ned Deily4ce92b22011-01-15 04:37:12 +00001453 # Check for problematic OS X Tk versions and print a warning message
1454 # in the IDLE shell window; this is less intrusive than always opening
1455 # a separate window.
1456 tkversionwarning = macosxSupport.tkVersionWarning(root)
1457 if tkversionwarning:
1458 shell.interp.runcommand(''.join(("print('", tkversionwarning, "')")))
1459
Terry Jan Reedycd6b8c62012-05-26 20:23:45 -04001460 while flist.inversedict: # keep IDLE running while files are open.
1461 root.mainloop()
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001462 root.destroy()
1463
David Scherer7aced172000-08-15 01:13:23 +00001464if __name__ == "__main__":
Kurt B. Kaiser9e8b8282003-06-15 17:38:45 +00001465 sys.modules['PyShell'] = sys.modules['__main__']
David Scherer7aced172000-08-15 01:13:23 +00001466 main()