blob: c524d61e4ee89a6136b3bf873ec30abcbf910fa8 [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:
Ned Deily55f87572011-11-05 22:36:44 -0700471 self.rpcclt.listening_sock.close()
472 except AttributeError: # no socket
473 pass
474 try:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000475 self.rpcclt.close()
476 except AttributeError: # no socket
477 pass
Ned Deilye5cad232011-08-02 18:47:13 -0700478 self.terminate_subprocess()
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000479 self.tkconsole.executing = False
480 self.rpcclt = None
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000481
Ned Deilye5cad232011-08-02 18:47:13 -0700482 def terminate_subprocess(self):
483 "Make sure subprocess is terminated"
484 try:
485 self.rpcsubproc.kill()
486 except OSError:
487 # process already terminated
488 return
489 else:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000490 try:
Ned Deilye5cad232011-08-02 18:47:13 -0700491 self.rpcsubproc.wait()
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000492 except OSError:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000493 return
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000494
Terry Jan Reedyda4c4672012-01-31 02:26:32 -0500495 def transfer_path(self, with_cwd=False):
496 if with_cwd: # Issue 13506
497 path = [''] # include Current Working Directory
498 path.extend(sys.path)
499 else:
500 path = sys.path
Terry Jan Reedy4d82ade2012-01-31 02:57:29 -0500501
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000502 self.runcommand("""if 1:
503 import sys as _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +0000504 _sys.path = %r
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000505 del _sys
Terry Jan Reedyda4c4672012-01-31 02:26:32 -0500506 \n""" % (path,))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000507
Chui Tey5d2af632002-05-26 13:36:41 +0000508 active_seq = None
509
510 def poll_subprocess(self):
511 clt = self.rpcclt
512 if clt is None:
513 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000514 try:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000515 response = clt.pollresponse(self.active_seq, wait=0.05)
516 except (EOFError, IOError, KeyboardInterrupt):
517 # lost connection or subprocess terminated itself, restart
518 # [the KBI is from rpc.SocketIO.handle_EOF()]
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000519 if self.tkconsole.closing:
520 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000521 response = None
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000522 self.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000523 if response:
524 self.tkconsole.resetoutput()
525 self.active_seq = None
526 how, what = response
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000527 console = self.tkconsole.console
Chui Tey5d2af632002-05-26 13:36:41 +0000528 if how == "OK":
529 if what is not None:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000530 print(repr(what), file=console)
Chui Tey5d2af632002-05-26 13:36:41 +0000531 elif how == "EXCEPTION":
Chui Tey5d2af632002-05-26 13:36:41 +0000532 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
533 self.remote_stack_viewer()
534 elif how == "ERROR":
Kurt B. Kaiser0930c432002-12-06 21:45:24 +0000535 errmsg = "PyShell.ModifiedInterpreter: Subprocess ERROR:\n"
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000536 print(errmsg, what, file=sys.__stderr__)
537 print(errmsg, what, file=console)
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000538 # we received a response to the currently active seq number:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000539 try:
540 self.tkconsole.endexecuting()
541 except AttributeError: # shell may have closed
542 pass
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000543 # Reschedule myself
544 if not self.tkconsole.closing:
545 self.tkconsole.text.after(self.tkconsole.pollinterval,
546 self.poll_subprocess)
Chui Tey5d2af632002-05-26 13:36:41 +0000547
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000548 debugger = None
549
550 def setdebugger(self, debugger):
551 self.debugger = debugger
552
553 def getdebugger(self):
554 return self.debugger
555
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000556 def open_remote_stack_viewer(self):
557 """Initiate the remote stack viewer from a separate thread.
558
559 This method is called from the subprocess, and by returning from this
560 method we allow the subprocess to unblock. After a bit the shell
561 requests the subprocess to open the remote stack viewer which returns a
Ezio Melotti60861182010-07-23 16:48:22 +0000562 static object looking at the last exception. It is queried through
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000563 the RPC mechanism.
564
565 """
566 self.tkconsole.text.after(300, self.remote_stack_viewer)
567 return
568
Chui Tey5d2af632002-05-26 13:36:41 +0000569 def remote_stack_viewer(self):
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000570 from idlelib import RemoteObjectBrowser
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000571 oid = self.rpcclt.remotequeue("exec", "stackviewer", ("flist",), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000572 if oid is None:
573 self.tkconsole.root.bell()
574 return
575 item = RemoteObjectBrowser.StubObjectTreeItem(self.rpcclt, oid)
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000576 from idlelib.TreeWidget import ScrolledCanvas, TreeNode
Chui Tey5d2af632002-05-26 13:36:41 +0000577 top = Toplevel(self.tkconsole.root)
Kurt B. Kaiser73360a32004-03-08 18:15:31 +0000578 theme = idleConf.GetOption('main','Theme','name')
579 background = idleConf.GetHighlight(theme, 'normal')['background']
580 sc = ScrolledCanvas(top, bg=background, highlightthickness=0)
Chui Tey5d2af632002-05-26 13:36:41 +0000581 sc.frame.pack(expand=1, fill="both")
582 node = TreeNode(sc.canvas, None, item)
583 node.expand()
584 # XXX Should GC the remote tree when closing the window
585
David Scherer7aced172000-08-15 01:13:23 +0000586 gid = 0
587
588 def execsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000589 "Like runsource() but assumes complete exec source"
David Scherer7aced172000-08-15 01:13:23 +0000590 filename = self.stuffsource(source)
591 self.execfile(filename, source)
592
593 def execfile(self, filename, source=None):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000594 "Execute an existing file"
David Scherer7aced172000-08-15 01:13:23 +0000595 if source is None:
Victor Stinner979482a2011-09-02 01:00:40 +0200596 with tokenize.open(filename) as fp:
Victor Stinner85c67722011-09-02 00:57:04 +0200597 source = fp.read()
David Scherer7aced172000-08-15 01:13:23 +0000598 try:
599 code = compile(source, filename, "exec")
600 except (OverflowError, SyntaxError):
601 self.tkconsole.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000602 tkerr = self.tkconsole.stderr
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000603 print('*** Error in script or command!\n', file=tkerr)
604 print('Traceback (most recent call last):', file=tkerr)
David Scherer7aced172000-08-15 01:13:23 +0000605 InteractiveInterpreter.showsyntaxerror(self, filename)
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000606 self.tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000607 else:
608 self.runcode(code)
609
610 def runsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000611 "Extend base class method: Stuff the source in the line cache first"
David Scherer7aced172000-08-15 01:13:23 +0000612 filename = self.stuffsource(source)
613 self.more = 0
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000614 self.save_warnings_filters = warnings.filters[:]
615 warnings.filterwarnings(action="error", category=SyntaxWarning)
Martin v. Löwis98ff8982007-08-13 06:03:15 +0000616 # at the moment, InteractiveInterpreter expects str
617 assert isinstance(source, str)
618 #if isinstance(source, str):
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000619 # from idlelib import IOBinding
Martin v. Löwis98ff8982007-08-13 06:03:15 +0000620 # try:
621 # source = source.encode(IOBinding.encoding)
622 # except UnicodeError:
623 # self.tkconsole.resetoutput()
624 # self.write("Unsupported characters in input\n")
625 # return
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000626 try:
Kurt B. Kaiser935ea9a2005-05-10 03:44:24 +0000627 # InteractiveInterpreter.runsource() calls its runcode() method,
628 # which is overridden (see below)
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000629 return InteractiveInterpreter.runsource(self, source, filename)
630 finally:
631 if self.save_warnings_filters is not None:
632 warnings.filters[:] = self.save_warnings_filters
633 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000634
635 def stuffsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000636 "Stuff source in the filename cache"
David Scherer7aced172000-08-15 01:13:23 +0000637 filename = "<pyshell#%d>" % self.gid
638 self.gid = self.gid + 1
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000639 lines = source.split("\n")
David Scherer7aced172000-08-15 01:13:23 +0000640 linecache.cache[filename] = len(source)+1, 0, lines, filename
641 return filename
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000642
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000643 def prepend_syspath(self, filename):
644 "Prepend sys.path with file's directory if not already included"
645 self.runcommand("""if 1:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000646 _filename = %r
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000647 import sys as _sys
648 from os.path import dirname as _dirname
649 _dir = _dirname(_filename)
650 if not _dir in _sys.path:
651 _sys.path.insert(0, _dir)
652 del _filename, _sys, _dirname, _dir
Walter Dörwald70a6b492004-02-12 17:35:32 +0000653 \n""" % (filename,))
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000654
David Scherer7aced172000-08-15 01:13:23 +0000655 def showsyntaxerror(self, filename=None):
Guido van Rossum33d26892007-08-05 15:29:28 +0000656 """Override Interactive Interpreter method: Use Colorizing
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000657
658 Color the offending position instead of printing it and pointing at it
659 with a caret.
660
661 """
Guido van Rossum33d26892007-08-05 15:29:28 +0000662 tkconsole = self.tkconsole
663 text = tkconsole.text
664 text.tag_remove("ERROR", "1.0", "end")
David Scherer7aced172000-08-15 01:13:23 +0000665 type, value, tb = sys.exc_info()
Ned Deily79746422011-09-14 14:49:14 -0700666 msg = getattr(value, 'msg', '') or value or "<no detail available>"
667 lineno = getattr(value, 'lineno', '') or 1
668 offset = getattr(value, 'offset', '') or 0
Guido van Rossum33d26892007-08-05 15:29:28 +0000669 if offset == 0:
670 lineno += 1 #mark end of offending line
671 if lineno == 1:
672 pos = "iomark + %d chars" % (offset-1)
David Scherer7aced172000-08-15 01:13:23 +0000673 else:
Guido van Rossum33d26892007-08-05 15:29:28 +0000674 pos = "iomark linestart + %d lines + %d chars" % \
675 (lineno-1, offset-1)
676 tkconsole.colorize_syntax_error(text, pos)
677 tkconsole.resetoutput()
678 self.write("SyntaxError: %s\n" % msg)
679 tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000680
681 def showtraceback(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000682 "Extend base class method to reset output properly"
David Scherer7aced172000-08-15 01:13:23 +0000683 self.tkconsole.resetoutput()
684 self.checklinecache()
685 InteractiveInterpreter.showtraceback(self)
Chui Tey5d2af632002-05-26 13:36:41 +0000686 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
687 self.tkconsole.open_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +0000688
689 def checklinecache(self):
690 c = linecache.cache
Guido van Rossum36e0a922007-07-20 04:05:57 +0000691 for key in list(c.keys()):
David Scherer7aced172000-08-15 01:13:23 +0000692 if key[:1] + key[-1:] != "<>":
693 del c[key]
694
Chui Tey5d2af632002-05-26 13:36:41 +0000695 def runcommand(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000696 "Run the code without invoking the debugger"
Chui Tey5d2af632002-05-26 13:36:41 +0000697 # The code better not raise an exception!
698 if self.tkconsole.executing:
Neal Norwitzf4c4f112002-11-30 18:49:10 +0000699 self.display_executing_dialog()
Chui Tey5d2af632002-05-26 13:36:41 +0000700 return 0
701 if self.rpcclt:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000702 self.rpcclt.remotequeue("exec", "runcode", (code,), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000703 else:
Georg Brandl7cae87c2006-09-06 06:51:57 +0000704 exec(code, self.locals)
Chui Tey5d2af632002-05-26 13:36:41 +0000705 return 1
706
David Scherer7aced172000-08-15 01:13:23 +0000707 def runcode(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000708 "Override base class method"
Chui Tey5d2af632002-05-26 13:36:41 +0000709 if self.tkconsole.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000710 self.interp.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000711 self.checklinecache()
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000712 if self.save_warnings_filters is not None:
713 warnings.filters[:] = self.save_warnings_filters
714 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000715 debugger = self.debugger
716 try:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000717 self.tkconsole.beginexecuting()
Thomas Wouterscf297e42007-02-23 15:07:44 +0000718 if not debugger and self.rpcclt is not None:
719 self.active_seq = self.rpcclt.asyncqueue("exec", "runcode",
720 (code,), {})
721 elif debugger:
722 debugger.run(code, self.locals)
723 else:
724 exec(code, self.locals)
725 except SystemExit:
726 if not self.tkconsole.closing:
727 if tkMessageBox.askyesno(
728 "Exit?",
729 "Do you want to exit altogether?",
730 default="yes",
731 master=self.tkconsole.text):
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000732 raise
Thomas Wouterscf297e42007-02-23 15:07:44 +0000733 else:
Guido van Rossum5dc0d972007-02-25 22:37:36 +0000734 self.showtraceback()
Thomas Wouterscf297e42007-02-23 15:07:44 +0000735 else:
736 raise
737 except:
738 if use_subprocess:
739 print("IDLE internal error in runcode()",
740 file=self.tkconsole.stderr)
David Scherer7aced172000-08-15 01:13:23 +0000741 self.showtraceback()
Thomas Wouterscf297e42007-02-23 15:07:44 +0000742 self.tkconsole.endexecuting()
743 else:
744 if self.tkconsole.canceled:
745 self.tkconsole.canceled = False
746 print("KeyboardInterrupt", file=self.tkconsole.stderr)
747 else:
748 self.showtraceback()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000749 finally:
750 if not use_subprocess:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000751 try:
752 self.tkconsole.endexecuting()
753 except AttributeError: # shell may have closed
754 pass
David Scherer7aced172000-08-15 01:13:23 +0000755
756 def write(self, s):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000757 "Override base class method"
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000758 self.tkconsole.stderr.write(s)
David Scherer7aced172000-08-15 01:13:23 +0000759
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000760 def display_port_binding_error(self):
761 tkMessageBox.showerror(
762 "Port Binding Error",
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000763 "IDLE can't bind to a TCP/IP port, which is necessary to "
764 "communicate with its Python execution server. This might be "
765 "because no networking is installed on this computer. "
766 "Run IDLE with the -n command line switch to start without a "
767 "subprocess and refer to Help/IDLE Help 'Running without a "
768 "subprocess' for further details.",
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000769 master=self.tkconsole.text)
770
771 def display_no_subprocess_error(self):
772 tkMessageBox.showerror(
773 "Subprocess Startup Error",
774 "IDLE's subprocess didn't make connection. Either IDLE can't "
775 "start a subprocess or personal firewall software is blocking "
776 "the connection.",
777 master=self.tkconsole.text)
778
779 def display_executing_dialog(self):
780 tkMessageBox.showerror(
781 "Already executing",
782 "The Python Shell window is already executing a command; "
783 "please wait until it is finished.",
784 master=self.tkconsole.text)
785
786
David Scherer7aced172000-08-15 01:13:23 +0000787class PyShell(OutputWindow):
788
789 shell_title = "Python Shell"
790
791 # Override classes
792 ColorDelegator = ModifiedColorDelegator
793 UndoDelegator = ModifiedUndoDelegator
794
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000795 # Override menus
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000796 menu_specs = [
797 ("file", "_File"),
798 ("edit", "_Edit"),
Kurt B. Kaiser4cc5ef52003-01-22 00:23:23 +0000799 ("debug", "_Debug"),
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000800 ("options", "_Options"),
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000801 ("windows", "_Windows"),
802 ("help", "_Help"),
803 ]
David Scherer7aced172000-08-15 01:13:23 +0000804
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000805 if macosxSupport.runningAsOSXApp():
806 del menu_specs[-3]
807 menu_specs[-2] = ("windows", "_Window")
808
809
David Scherer7aced172000-08-15 01:13:23 +0000810 # New classes
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000811 from idlelib.IdleHistory import History
David Scherer7aced172000-08-15 01:13:23 +0000812
813 def __init__(self, flist=None):
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000814 if use_subprocess:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000815 ms = self.menu_specs
816 if ms[2][0] != "shell":
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000817 ms.insert(2, ("shell", "She_ll"))
David Scherer7aced172000-08-15 01:13:23 +0000818 self.interp = ModifiedInterpreter(self)
819 if flist is None:
820 root = Tk()
821 fixwordbreaks(root)
822 root.withdraw()
823 flist = PyShellFileList(root)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000824 #
David Scherer7aced172000-08-15 01:13:23 +0000825 OutputWindow.__init__(self, flist, None, None)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000826 #
Kurt B. Kaiser6af44982005-01-19 00:22:59 +0000827## self.config(usetabs=1, indentwidth=8, context_use_ps1=1)
828 self.usetabs = True
829 # indentwidth must be 8 when using tabs. See note in EditorWindow:
830 self.indentwidth = 8
831 self.context_use_ps1 = True
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000832 #
David Scherer7aced172000-08-15 01:13:23 +0000833 text = self.text
834 text.configure(wrap="char")
835 text.bind("<<newline-and-indent>>", self.enter_callback)
836 text.bind("<<plain-newline-and-indent>>", self.linefeed_callback)
837 text.bind("<<interrupt-execution>>", self.cancel_callback)
David Scherer7aced172000-08-15 01:13:23 +0000838 text.bind("<<end-of-file>>", self.eof_callback)
839 text.bind("<<open-stack-viewer>>", self.open_stack_viewer)
Kurt B. Kaiser57bfe5d2003-05-10 00:09:52 +0000840 text.bind("<<toggle-debugger>>", self.toggle_debugger)
David Scherer7aced172000-08-15 01:13:23 +0000841 text.bind("<<toggle-jit-stack-viewer>>", self.toggle_jit_stack_viewer)
Kurt B. Kaiser8a78cad2007-12-13 03:38:16 +0000842 self.color = color = self.ColorDelegator()
843 self.per.insertfilter(color)
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000844 if use_subprocess:
845 text.bind("<<view-restart>>", self.view_restart_mark)
846 text.bind("<<restart-shell>>", self.restart_shell)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000847 #
David Scherer7aced172000-08-15 01:13:23 +0000848 self.save_stdout = sys.stdout
849 self.save_stderr = sys.stderr
850 self.save_stdin = sys.stdin
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000851 from idlelib import IOBinding
Martin v. Löwisbcc651a2003-06-22 07:52:56 +0000852 self.stdout = PseudoFile(self, "stdout", IOBinding.encoding)
853 self.stderr = PseudoFile(self, "stderr", IOBinding.encoding)
854 self.console = PseudoFile(self, "console", IOBinding.encoding)
Chui Tey5d2af632002-05-26 13:36:41 +0000855 if not use_subprocess:
856 sys.stdout = self.stdout
Kurt B. Kaiser7cec2522007-08-31 04:15:13 +0000857 sys.stderr = self.stderr
Chui Tey5d2af632002-05-26 13:36:41 +0000858 sys.stdin = self
Kurt B. Kaiserf609a342007-12-28 03:57:56 +0000859 try:
860 # page help() text to shell.
861 import pydoc # import must be done here to capture i/o rebinding.
862 # XXX KBK 27Dec07 use a textView someday, but must work w/o subproc
863 pydoc.pager = pydoc.plainpager
864 except:
865 sys.stderr = sys.__stderr__
866 raise
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000867 #
David Scherer7aced172000-08-15 01:13:23 +0000868 self.history = self.History(self.text)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000869 #
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000870 self.pollinterval = 50 # millisec
Chui Tey5d2af632002-05-26 13:36:41 +0000871
Kurt B. Kaiser4d5bc602004-06-06 01:29:22 +0000872 def get_standard_extension_names(self):
873 return idleConf.GetExtensions(shell_only=True)
874
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000875 reading = False
876 executing = False
877 canceled = False
878 endoffile = False
879 closing = False
David Scherer7aced172000-08-15 01:13:23 +0000880
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +0000881 def set_warning_stream(self, stream):
Skip Montanarod9161422004-07-06 21:53:27 +0000882 global warning_stream
883 warning_stream = stream
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +0000884
885 def get_warning_stream(self):
886 return warning_stream
887
David Scherer7aced172000-08-15 01:13:23 +0000888 def toggle_debugger(self, event=None):
889 if self.executing:
890 tkMessageBox.showerror("Don't debug now",
891 "You can only toggle the debugger when idle",
892 master=self.text)
893 self.set_debugger_indicator()
894 return "break"
895 else:
896 db = self.interp.getdebugger()
897 if db:
898 self.close_debugger()
899 else:
900 self.open_debugger()
901
902 def set_debugger_indicator(self):
903 db = self.interp.getdebugger()
904 self.setvar("<<toggle-debugger>>", not not db)
905
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000906 def toggle_jit_stack_viewer(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +0000907 pass # All we need is the variable
908
909 def close_debugger(self):
910 db = self.interp.getdebugger()
911 if db:
912 self.interp.setdebugger(None)
913 db.close()
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000914 if self.interp.rpcclt:
915 RemoteDebugger.close_remote_debugger(self.interp.rpcclt)
David Scherer7aced172000-08-15 01:13:23 +0000916 self.resetoutput()
917 self.console.write("[DEBUG OFF]\n")
918 sys.ps1 = ">>> "
919 self.showprompt()
920 self.set_debugger_indicator()
921
922 def open_debugger(self):
Chui Tey5d2af632002-05-26 13:36:41 +0000923 if self.interp.rpcclt:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000924 dbg_gui = RemoteDebugger.start_remote_debugger(self.interp.rpcclt,
925 self)
926 else:
927 dbg_gui = Debugger.Debugger(self)
928 self.interp.setdebugger(dbg_gui)
929 dbg_gui.load_breakpoints()
Chui Tey5d2af632002-05-26 13:36:41 +0000930 sys.ps1 = "[DEBUG ON]\n>>> "
931 self.showprompt()
932 self.set_debugger_indicator()
933
David Scherer7aced172000-08-15 01:13:23 +0000934 def beginexecuting(self):
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000935 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +0000936 self.resetoutput()
937 self.executing = 1
David Scherer7aced172000-08-15 01:13:23 +0000938
939 def endexecuting(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000940 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +0000941 self.executing = 0
942 self.canceled = 0
Chui Tey5d2af632002-05-26 13:36:41 +0000943 self.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000944
945 def close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000946 "Extend EditorWindow.close()"
David Scherer7aced172000-08-15 01:13:23 +0000947 if self.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000948 response = tkMessageBox.askokcancel(
David Scherer7aced172000-08-15 01:13:23 +0000949 "Kill?",
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000950 "The program is still running!\n Do you want to kill it?",
David Scherer7aced172000-08-15 01:13:23 +0000951 default="ok",
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000952 parent=self.text)
Benjamin Peterson2a691a82008-03-31 01:51:45 +0000953 if response is False:
David Scherer7aced172000-08-15 01:13:23 +0000954 return "cancel"
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +0000955 if self.reading:
956 self.top.quit()
957 self.canceled = True
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000958 self.closing = True
959 # Wait for poll_subprocess() rescheduling to stop
960 self.text.after(2 * self.pollinterval, self.close2)
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000961
962 def close2(self):
963 return EditorWindow.close(self)
David Scherer7aced172000-08-15 01:13:23 +0000964
965 def _close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000966 "Extend EditorWindow._close(), shut down debugger and execution server"
David Scherer7aced172000-08-15 01:13:23 +0000967 self.close_debugger()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000968 if use_subprocess:
969 self.interp.kill_subprocess()
David Scherer7aced172000-08-15 01:13:23 +0000970 # Restore std streams
971 sys.stdout = self.save_stdout
972 sys.stderr = self.save_stderr
973 sys.stdin = self.save_stdin
974 # Break cycles
975 self.interp = None
976 self.console = None
David Scherer7aced172000-08-15 01:13:23 +0000977 self.flist.pyshell = None
978 self.history = None
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000979 EditorWindow._close(self)
David Scherer7aced172000-08-15 01:13:23 +0000980
981 def ispythonsource(self, filename):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000982 "Override EditorWindow method: never remove the colorizer"
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000983 return True
David Scherer7aced172000-08-15 01:13:23 +0000984
985 def short_title(self):
986 return self.shell_title
987
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000988 COPYRIGHT = \
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000989 'Type "copyright", "credits" or "license()" for more information.'
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000990
David Scherer7aced172000-08-15 01:13:23 +0000991 def begin(self):
Kurt B. Kaiser7378df72007-08-11 04:20:51 +0000992 self.text.mark_set("iomark", "insert")
David Scherer7aced172000-08-15 01:13:23 +0000993 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000994 if use_subprocess:
995 nosub = ''
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000996 client = self.interp.start_subprocess()
997 if not client:
998 self.close()
Kurt B. Kaiser76637292004-01-21 22:10:01 +0000999 return False
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001000 else:
1001 nosub = "==== No Subprocess ===="
Andrew Svetlovcd49d532012-03-25 11:43:02 +03001002 sys.displayhook = rpc.displayhook
1003
Raymond Hettingera2a8e8b2009-01-27 00:28:36 +00001004 self.write("Python %s on %s\n%s\n%s" %
1005 (sys.version, sys.platform, self.COPYRIGHT, nosub))
David Scherer7aced172000-08-15 01:13:23 +00001006 self.showprompt()
Georg Brandl14fc4272008-05-17 18:39:55 +00001007 import tkinter
1008 tkinter._default_root = None # 03Jan04 KBK What's this?
Kurt B. Kaiser76637292004-01-21 22:10:01 +00001009 return True
David Scherer7aced172000-08-15 01:13:23 +00001010
1011 def readline(self):
1012 save = self.reading
1013 try:
1014 self.reading = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001015 self.top.mainloop() # nested mainloop()
David Scherer7aced172000-08-15 01:13:23 +00001016 finally:
1017 self.reading = save
1018 line = self.text.get("iomark", "end-1c")
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001019 if len(line) == 0: # may be EOF if we quit our mainloop with Ctrl-C
1020 line = "\n"
David Scherer7aced172000-08-15 01:13:23 +00001021 self.resetoutput()
1022 if self.canceled:
1023 self.canceled = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001024 if not use_subprocess:
1025 raise KeyboardInterrupt
David Scherer7aced172000-08-15 01:13:23 +00001026 if self.endoffile:
1027 self.endoffile = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001028 line = ""
David Scherer7aced172000-08-15 01:13:23 +00001029 return line
1030
1031 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001032 return True
David Scherer7aced172000-08-15 01:13:23 +00001033
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001034 def cancel_callback(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +00001035 try:
1036 if self.text.compare("sel.first", "!=", "sel.last"):
1037 return # Active selection -- always use default binding
1038 except:
1039 pass
1040 if not (self.executing or self.reading):
1041 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001042 self.interp.write("KeyboardInterrupt\n")
David Scherer7aced172000-08-15 01:13:23 +00001043 self.showprompt()
1044 return "break"
1045 self.endoffile = 0
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001046 self.canceled = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001047 if (self.executing and self.interp.rpcclt):
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +00001048 if self.interp.getdebugger():
1049 self.interp.restart_subprocess()
1050 else:
1051 self.interp.interrupt_subprocess()
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001052 if self.reading:
1053 self.top.quit() # exit the nested mainloop() in readline()
David Scherer7aced172000-08-15 01:13:23 +00001054 return "break"
1055
1056 def eof_callback(self, event):
1057 if self.executing and not self.reading:
1058 return # Let the default binding (delete next char) take over
1059 if not (self.text.compare("iomark", "==", "insert") and
1060 self.text.compare("insert", "==", "end-1c")):
1061 return # Let the default binding (delete next char) take over
1062 if not self.executing:
David Scherer7aced172000-08-15 01:13:23 +00001063 self.resetoutput()
1064 self.close()
1065 else:
1066 self.canceled = 0
1067 self.endoffile = 1
1068 self.top.quit()
1069 return "break"
1070
David Scherer7aced172000-08-15 01:13:23 +00001071 def linefeed_callback(self, event):
1072 # Insert a linefeed without entering anything (still autoindented)
1073 if self.reading:
1074 self.text.insert("insert", "\n")
1075 self.text.see("insert")
1076 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001077 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001078 return "break"
1079
1080 def enter_callback(self, event):
1081 if self.executing and not self.reading:
1082 return # Let the default binding (insert '\n') take over
1083 # If some text is selected, recall the selection
1084 # (but only if this before the I/O mark)
1085 try:
1086 sel = self.text.get("sel.first", "sel.last")
1087 if sel:
1088 if self.text.compare("sel.last", "<=", "iomark"):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001089 self.recall(sel, event)
David Scherer7aced172000-08-15 01:13:23 +00001090 return "break"
1091 except:
1092 pass
1093 # If we're strictly before the line containing iomark, recall
1094 # the current line, less a leading prompt, less leading or
1095 # trailing whitespace
1096 if self.text.compare("insert", "<", "iomark linestart"):
1097 # Check if there's a relevant stdin range -- if so, use it
1098 prev = self.text.tag_prevrange("stdin", "insert")
1099 if prev and self.text.compare("insert", "<", prev[1]):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001100 self.recall(self.text.get(prev[0], prev[1]), event)
David Scherer7aced172000-08-15 01:13:23 +00001101 return "break"
1102 next = self.text.tag_nextrange("stdin", "insert")
1103 if next and self.text.compare("insert lineend", ">=", next[0]):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001104 self.recall(self.text.get(next[0], next[1]), event)
David Scherer7aced172000-08-15 01:13:23 +00001105 return "break"
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001106 # No stdin mark -- just get the current line, less any prompt
Kurt B. Kaiserb1754452005-11-18 22:05:48 +00001107 indices = self.text.tag_nextrange("console", "insert linestart")
1108 if indices and \
1109 self.text.compare(indices[0], "<=", "insert linestart"):
1110 self.recall(self.text.get(indices[1], "insert lineend"), event)
1111 else:
1112 self.recall(self.text.get("insert linestart", "insert lineend"), event)
David Scherer7aced172000-08-15 01:13:23 +00001113 return "break"
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001114 # If we're between the beginning of the line and the iomark, i.e.
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001115 # in the prompt area, move to the end of the prompt
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001116 if self.text.compare("insert", "<", "iomark"):
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001117 self.text.mark_set("insert", "iomark")
David Scherer7aced172000-08-15 01:13:23 +00001118 # If we're in the current input and there's only whitespace
1119 # beyond the cursor, erase that whitespace first
1120 s = self.text.get("insert", "end-1c")
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001121 if s and not s.strip():
David Scherer7aced172000-08-15 01:13:23 +00001122 self.text.delete("insert", "end-1c")
1123 # If we're in the current input before its last line,
1124 # insert a newline right at the insert point
1125 if self.text.compare("insert", "<", "end-1c linestart"):
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001126 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001127 return "break"
1128 # We're in the last line; append a newline and submit it
1129 self.text.mark_set("insert", "end-1c")
1130 if self.reading:
1131 self.text.insert("insert", "\n")
1132 self.text.see("insert")
1133 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001134 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001135 self.text.tag_add("stdin", "iomark", "end-1c")
1136 self.text.update_idletasks()
1137 if self.reading:
Neal Norwitzce96f692006-03-17 06:49:51 +00001138 self.top.quit() # Break out of recursive mainloop()
David Scherer7aced172000-08-15 01:13:23 +00001139 else:
1140 self.runit()
1141 return "break"
1142
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001143 def recall(self, s, event):
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001144 # remove leading and trailing empty or whitespace lines
1145 s = re.sub(r'^\s*\n', '' , s)
1146 s = re.sub(r'\n\s*$', '', s)
1147 lines = s.split('\n')
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001148 self.text.undo_block_start()
1149 try:
1150 self.text.tag_remove("sel", "1.0", "end")
1151 self.text.mark_set("insert", "end-1c")
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001152 prefix = self.text.get("insert linestart", "insert")
1153 if prefix.rstrip().endswith(':'):
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001154 self.newline_and_indent_event(event)
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001155 prefix = self.text.get("insert linestart", "insert")
1156 self.text.insert("insert", lines[0].strip())
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001157 if len(lines) > 1:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001158 orig_base_indent = re.search(r'^([ \t]*)', lines[0]).group(0)
1159 new_base_indent = re.search(r'^([ \t]*)', prefix).group(0)
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001160 for line in lines[1:]:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001161 if line.startswith(orig_base_indent):
1162 # replace orig base indentation with new indentation
1163 line = new_base_indent + line[len(orig_base_indent):]
1164 self.text.insert('insert', '\n'+line.rstrip())
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001165 finally:
1166 self.text.see("insert")
1167 self.text.undo_block_stop()
David Scherer7aced172000-08-15 01:13:23 +00001168
1169 def runit(self):
1170 line = self.text.get("iomark", "end-1c")
1171 # Strip off last newline and surrounding whitespace.
1172 # (To allow you to hit return twice to end a statement.)
1173 i = len(line)
1174 while i > 0 and line[i-1] in " \t":
1175 i = i-1
1176 if i > 0 and line[i-1] == "\n":
1177 i = i-1
1178 while i > 0 and line[i-1] in " \t":
1179 i = i-1
1180 line = line[:i]
1181 more = self.interp.runsource(line)
David Scherer7aced172000-08-15 01:13:23 +00001182
David Scherer7aced172000-08-15 01:13:23 +00001183 def open_stack_viewer(self, event=None):
Chui Tey5d2af632002-05-26 13:36:41 +00001184 if self.interp.rpcclt:
1185 return self.interp.remote_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +00001186 try:
1187 sys.last_traceback
1188 except:
1189 tkMessageBox.showerror("No stack trace",
1190 "There is no stack trace yet.\n"
1191 "(sys.last_traceback is not defined)",
1192 master=self.text)
1193 return
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +00001194 from idlelib.StackViewer import StackBrowser
David Scherer7aced172000-08-15 01:13:23 +00001195 sv = StackBrowser(self.root, self.flist)
1196
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001197 def view_restart_mark(self, event=None):
1198 self.text.see("iomark")
1199 self.text.see("restart")
1200
1201 def restart_shell(self, event=None):
Terry Jan Reedyda4c4672012-01-31 02:26:32 -05001202 "Callback for Run/Restart Shell Cntl-F6"
1203 self.interp.restart_subprocess(with_cwd=True)
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001204
David Scherer7aced172000-08-15 01:13:23 +00001205 def showprompt(self):
1206 self.resetoutput()
1207 try:
1208 s = str(sys.ps1)
1209 except:
1210 s = ""
1211 self.console.write(s)
1212 self.text.mark_set("insert", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001213 self.set_line_and_column()
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +00001214 self.io.reset_undo()
David Scherer7aced172000-08-15 01:13:23 +00001215
1216 def resetoutput(self):
1217 source = self.text.get("iomark", "end-1c")
1218 if self.history:
1219 self.history.history_store(source)
1220 if self.text.get("end-2c") != "\n":
1221 self.text.insert("end-1c", "\n")
1222 self.text.mark_set("iomark", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001223 self.set_line_and_column()
David Scherer7aced172000-08-15 01:13:23 +00001224
1225 def write(self, s, tags=()):
Andrew Svetlov05bab932012-03-14 13:22:12 -07001226 if isinstance(s, str) and len(s) and max(s) > '\uffff':
1227 # Tk doesn't support outputting non-BMP characters
1228 # Let's assume what printed string is not very long,
1229 # find first non-BMP character and construct informative
1230 # UnicodeEncodeError exception.
1231 for start, char in enumerate(s):
1232 if char > '\uffff':
1233 break
1234 raise UnicodeEncodeError("UCS-2", char, start, start+1,
1235 'Non-BMP character not supported in Tk')
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001236 try:
1237 self.text.mark_gravity("iomark", "right")
1238 OutputWindow.write(self, s, tags, "iomark")
1239 self.text.mark_gravity("iomark", "left")
1240 except:
Kurt B. Kaisercbbe98f2007-08-12 01:52:35 +00001241 raise ###pass # ### 11Aug07 KBK if we are expecting exceptions
1242 # let's find out what they are and be specific.
David Scherer7aced172000-08-15 01:13:23 +00001243 if self.canceled:
1244 self.canceled = 0
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001245 if not use_subprocess:
1246 raise KeyboardInterrupt
David Scherer7aced172000-08-15 01:13:23 +00001247
Kurt B. Kaiserdcba6622004-12-21 22:10:32 +00001248class PseudoFile(object):
David Scherer7aced172000-08-15 01:13:23 +00001249
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001250 def __init__(self, shell, tags, encoding=None):
David Scherer7aced172000-08-15 01:13:23 +00001251 self.shell = shell
1252 self.tags = tags
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001253 self.encoding = encoding
David Scherer7aced172000-08-15 01:13:23 +00001254
1255 def write(self, s):
1256 self.shell.write(s, self.tags)
1257
Kurt B. Kaiser66aaf742007-08-09 18:00:23 +00001258 def writelines(self, lines):
1259 for line in lines:
1260 self.write(line)
David Scherer7aced172000-08-15 01:13:23 +00001261
1262 def flush(self):
1263 pass
1264
1265 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001266 return True
David Scherer7aced172000-08-15 01:13:23 +00001267
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001268
David Scherer7aced172000-08-15 01:13:23 +00001269usage_msg = """\
David Scherer7aced172000-08-15 01:13:23 +00001270
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001271USAGE: idle [-deins] [-t title] [file]*
1272 idle [-dns] [-t title] (-c cmd | -r file) [arg]*
1273 idle [-dns] [-t title] - [arg]*
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001274
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001275 -h print this help message and exit
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001276 -n run IDLE without a subprocess (see Help/IDLE Help for details)
David Scherer7aced172000-08-15 01:13:23 +00001277
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001278The following options will override the IDLE 'settings' configuration:
Kurt B. Kaiser96d88422001-07-17 04:59:01 +00001279
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001280 -e open an edit window
1281 -i open a shell window
1282
1283The following options imply -i and will open a shell:
1284
1285 -c cmd run the command in a shell, or
1286 -r file run script from file
1287
1288 -d enable the debugger
1289 -s run $IDLESTARTUP or $PYTHONSTARTUP before anything else
1290 -t title set title of shell window
1291
1292A default edit window will be bypassed when -c, -r, or - are used.
1293
1294[arg]* are passed to the command (-c) or script (-r) in sys.argv[1:].
1295
1296Examples:
1297
1298idle
1299 Open an edit window or shell depending on IDLE's configuration.
1300
1301idle foo.py foobar.py
1302 Edit the files, also open a shell if configured to start with shell.
1303
1304idle -est "Baz" foo.py
1305 Run $IDLESTARTUP or $PYTHONSTARTUP, edit foo.py, and open a shell
1306 window with the title "Baz".
1307
Neal Norwitz752abd02008-05-13 04:55:24 +00001308idle -c "import sys; print(sys.argv)" "foo"
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001309 Open a shell window and run the command, passing "-c" in sys.argv[0]
1310 and "foo" in sys.argv[1].
1311
1312idle -d -s -r foo.py "Hello World"
1313 Open a shell window, run a startup script, enable the debugger, and
1314 run foo.py, passing "foo.py" in sys.argv[0] and "Hello World" in
1315 sys.argv[1].
1316
Neal Norwitz752abd02008-05-13 04:55:24 +00001317echo "import sys; print(sys.argv)" | idle - "foobar"
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001318 Open a shell window, run the script piped in, passing '' in sys.argv[0]
1319 and "foobar" in sys.argv[1].
David Scherer7aced172000-08-15 01:13:23 +00001320"""
1321
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001322def main():
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001323 global flist, root, use_subprocess
David Scherer7aced172000-08-15 01:13:23 +00001324
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001325 use_subprocess = True
Kurt B. Kaisere866c812009-04-04 21:07:39 +00001326 enable_shell = True
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001327 enable_edit = False
1328 debug = False
1329 cmd = None
1330 script = None
1331 startup = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001332 try:
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001333 opts, args = getopt.getopt(sys.argv[1:], "c:deihnr:st:")
Guido van Rossumb940e112007-01-10 16:19:56 +00001334 except getopt.error as msg:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001335 sys.stderr.write("Error: %s\n" % str(msg))
1336 sys.stderr.write(usage_msg)
1337 sys.exit(2)
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001338 for o, a in opts:
1339 if o == '-c':
1340 cmd = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001341 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001342 if o == '-d':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001343 debug = True
1344 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001345 if o == '-e':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001346 enable_edit = True
Kurt B. Kaisere866c812009-04-04 21:07:39 +00001347 enable_shell = False
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001348 if o == '-h':
1349 sys.stdout.write(usage_msg)
1350 sys.exit()
1351 if o == '-i':
1352 enable_shell = True
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001353 if o == '-n':
1354 use_subprocess = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001355 if o == '-r':
1356 script = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001357 if os.path.isfile(script):
1358 pass
1359 else:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001360 print("No script file: ", script)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001361 sys.exit()
1362 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001363 if o == '-s':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001364 startup = True
1365 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001366 if o == '-t':
1367 PyShell.shell_title = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001368 enable_shell = True
1369 if args and args[0] == '-':
1370 cmd = sys.stdin.read()
1371 enable_shell = True
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001372 # process sys.argv and sys.path:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001373 for i in range(len(sys.path)):
1374 sys.path[i] = os.path.abspath(sys.path[i])
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001375 if args and args[0] == '-':
1376 sys.argv = [''] + args[1:]
1377 elif cmd:
1378 sys.argv = ['-c'] + args
1379 elif script:
1380 sys.argv = [script] + args
1381 elif args:
1382 enable_edit = True
1383 pathx = []
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001384 for filename in args:
1385 pathx.append(os.path.dirname(filename))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001386 for dir in pathx:
1387 dir = os.path.abspath(dir)
1388 if not dir in sys.path:
1389 sys.path.insert(0, dir)
Kurt B. Kaiserff002b92002-12-21 21:39:11 +00001390 else:
Neal Norwitzd082b6e2007-08-26 23:37:53 +00001391 dir = os.getcwd()
1392 if dir not in sys.path:
Kurt B. Kaiserff002b92002-12-21 21:39:11 +00001393 sys.path.insert(0, dir)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001394 # check the IDLE settings configuration (but command line overrides)
1395 edit_start = idleConf.GetOption('main', 'General',
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001396 'editor-on-startup', type='bool')
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001397 enable_edit = enable_edit or edit_start
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001398 # start editor and/or shell windows:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001399 root = Tk(className="Idle")
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001400
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001401 fixwordbreaks(root)
1402 root.withdraw()
1403 flist = PyShellFileList(root)
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001404 macosxSupport.setupApp(root, flist)
1405
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001406 if enable_edit:
1407 if not (cmd or script):
Andrew Svetlov6b6e4372012-03-20 23:03:26 +02001408 for filename in args[:]:
1409 if flist.open(filename) is None:
1410 # filename is a directory actually, disconsider it
1411 args.remove(filename)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001412 if not args:
1413 flist.new()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001414 if enable_shell:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001415 shell = flist.open_shell()
1416 if not shell:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001417 return # couldn't open shell
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001418
1419 if macosxSupport.runningAsOSXApp() and flist.dict:
1420 # On OSX: when the user has double-clicked on a file that causes
1421 # IDLE to be launched the shell window will open just in front of
1422 # the file she wants to see. Lower the interpreter window when
1423 # there are open files.
1424 shell.top.lower()
1425
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001426 shell = flist.pyshell
1427 # handle remaining options:
1428 if debug:
1429 shell.open_debugger()
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001430 if startup:
1431 filename = os.environ.get("IDLESTARTUP") or \
1432 os.environ.get("PYTHONSTARTUP")
1433 if filename and os.path.isfile(filename):
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001434 shell.interp.execfile(filename)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001435 if shell and cmd or script:
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001436 shell.interp.runcommand("""if 1:
1437 import sys as _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001438 _sys.argv = %r
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001439 del _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001440 \n""" % (sys.argv,))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001441 if cmd:
1442 shell.interp.execsource(cmd)
1443 elif script:
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001444 shell.interp.prepend_syspath(script)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001445 shell.interp.execfile(script)
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001446
Ned Deily4ce92b22011-01-15 04:37:12 +00001447 # Check for problematic OS X Tk versions and print a warning message
1448 # in the IDLE shell window; this is less intrusive than always opening
1449 # a separate window.
1450 tkversionwarning = macosxSupport.tkVersionWarning(root)
1451 if tkversionwarning:
1452 shell.interp.runcommand(''.join(("print('", tkversionwarning, "')")))
1453
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001454 root.mainloop()
1455 root.destroy()
1456
David Scherer7aced172000-08-15 01:13:23 +00001457if __name__ == "__main__":
Kurt B. Kaiser9e8b8282003-06-15 17:38:45 +00001458 sys.modules['PyShell'] = sys.modules['__main__']
David Scherer7aced172000-08-15 01:13:23 +00001459 main()