blob: bff52a9708a52a17f137934f5102f653ee346173 [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
Andrew Svetlovd1837672012-11-01 22:41:19 +0200120 rmenu_specs = [
121 ("Cut", "<<cut>>", "rmenu_check_cut"),
122 ("Copy", "<<copy>>", "rmenu_check_copy"),
123 ("Paste", "<<paste>>", "rmenu_check_paste"),
124 (None, None, None),
125 ("Set Breakpoint", "<<set-breakpoint-here>>", None),
126 ("Clear Breakpoint", "<<clear-breakpoint-here>>", None)
127 ]
David Scherer7aced172000-08-15 01:13:23 +0000128
Chui Teya2adb0f2002-11-04 22:14:54 +0000129 def set_breakpoint(self, lineno):
130 text = self.text
131 filename = self.io.filename
132 text.tag_add("BREAK", "%d.0" % lineno, "%d.0" % (lineno+1))
133 try:
134 i = self.breakpoints.index(lineno)
135 except ValueError: # only add if missing, i.e. do once
136 self.breakpoints.append(lineno)
137 try: # update the subprocess debugger
138 debug = self.flist.pyshell.interp.debugger
139 debug.set_breakpoint_here(filename, lineno)
140 except: # but debugger may not be active right now....
141 pass
142
David Scherer7aced172000-08-15 01:13:23 +0000143 def set_breakpoint_here(self, event=None):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000144 text = self.text
145 filename = self.io.filename
146 if not filename:
147 text.bell()
David Scherer7aced172000-08-15 01:13:23 +0000148 return
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000149 lineno = int(float(text.index("insert")))
Chui Teya2adb0f2002-11-04 22:14:54 +0000150 self.set_breakpoint(lineno)
David Scherer7aced172000-08-15 01:13:23 +0000151
Kurt B. Kaiser669f4c32002-06-20 04:01:47 +0000152 def clear_breakpoint_here(self, event=None):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000153 text = self.text
154 filename = self.io.filename
155 if not filename:
156 text.bell()
Kurt B. Kaiser669f4c32002-06-20 04:01:47 +0000157 return
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000158 lineno = int(float(text.index("insert")))
159 try:
160 self.breakpoints.remove(lineno)
161 except:
162 pass
163 text.tag_remove("BREAK", "insert linestart",\
164 "insert lineend +1char")
165 try:
166 debug = self.flist.pyshell.interp.debugger
167 debug.clear_breakpoint_here(filename, lineno)
168 except:
169 pass
170
171 def clear_file_breaks(self):
172 if self.breakpoints:
173 text = self.text
174 filename = self.io.filename
175 if not filename:
176 text.bell()
177 return
178 self.breakpoints = []
179 text.tag_remove("BREAK", "1.0", END)
180 try:
181 debug = self.flist.pyshell.interp.debugger
182 debug.clear_file_breaks(filename)
183 except:
184 pass
185
Chui Teya2adb0f2002-11-04 22:14:54 +0000186 def store_file_breaks(self):
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000187 "Save breakpoints when file is saved"
188 # XXX 13 Dec 2002 KBK Currently the file must be saved before it can
189 # be run. The breaks are saved at that time. If we introduce
190 # a temporary file save feature the save breaks functionality
191 # needs to be re-verified, since the breaks at the time the
192 # temp file is created may differ from the breaks at the last
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000193 # permanent save of the file. Currently, a break introduced
194 # after a save will be effective, but not persistent.
195 # This is necessary to keep the saved breaks synched with the
196 # saved file.
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000197 #
198 # Breakpoints are set as tagged ranges in the text. Certain
199 # kinds of edits cause these ranges to be deleted: Inserting
200 # or deleting a line just before a breakpoint, and certain
201 # deletions prior to a breakpoint. These issues need to be
202 # investigated and understood. It's not clear if they are
203 # Tk issues or IDLE issues, or whether they can actually
204 # be fixed. Since a modified file has to be saved before it is
205 # run, and since self.breakpoints (from which the subprocess
206 # debugger is loaded) is updated during the save, the visible
207 # breaks stay synched with the subprocess even if one of these
208 # unexpected breakpoint deletions occurs.
209 breaks = self.breakpoints
210 filename = self.io.filename
Chui Teya2adb0f2002-11-04 22:14:54 +0000211 try:
Victor Stinner85c67722011-09-02 00:57:04 +0200212 with open(self.breakpointPath, "r") as fp:
213 lines = fp.readlines()
Chui Teya2adb0f2002-11-04 22:14:54 +0000214 except IOError:
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000215 lines = []
Ned Deilyf505b742011-12-14 14:58:24 -0800216 try:
217 with open(self.breakpointPath, "w") as new_file:
218 for line in lines:
219 if not line.startswith(filename + '='):
220 new_file.write(line)
221 self.update_breakpoints()
222 breaks = self.breakpoints
223 if breaks:
224 new_file.write(filename + '=' + str(breaks) + '\n')
225 except IOError as err:
226 if not getattr(self.root, "breakpoint_error_displayed", False):
227 self.root.breakpoint_error_displayed = True
228 tkMessageBox.showerror(title='IDLE Error',
229 message='Unable to update breakpoint list:\n%s'
230 % str(err),
231 parent=self.text)
Chui Teya2adb0f2002-11-04 22:14:54 +0000232
233 def restore_file_breaks(self):
234 self.text.update() # this enables setting "BREAK" tags to be visible
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000235 filename = self.io.filename
236 if filename is None:
237 return
Chui Tey69371d62002-11-04 23:39:45 +0000238 if os.path.isfile(self.breakpointPath):
Victor Stinner85c67722011-09-02 00:57:04 +0200239 with open(self.breakpointPath, "r") as fp:
240 lines = fp.readlines()
Chui Tey69371d62002-11-04 23:39:45 +0000241 for line in lines:
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000242 if line.startswith(filename + '='):
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000243 breakpoint_linenumbers = eval(line[len(filename)+1:])
Chui Tey69371d62002-11-04 23:39:45 +0000244 for breakpoint_linenumber in breakpoint_linenumbers:
245 self.set_breakpoint(breakpoint_linenumber)
Chui Teya2adb0f2002-11-04 22:14:54 +0000246
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000247 def update_breakpoints(self):
248 "Retrieves all the breakpoints in the current window"
Chui Teya2adb0f2002-11-04 22:14:54 +0000249 text = self.text
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000250 ranges = text.tag_ranges("BREAK")
251 linenumber_list = self.ranges_to_linenumbers(ranges)
252 self.breakpoints = linenumber_list
253
254 def ranges_to_linenumbers(self, ranges):
255 lines = []
256 for index in range(0, len(ranges), 2):
Andrew Svetlov06c5c6d2012-07-31 19:48:00 +0300257 lineno = int(float(ranges[index].string))
258 end = int(float(ranges[index+1].string))
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000259 while lineno < end:
260 lines.append(lineno)
261 lineno += 1
262 return lines
263
Kurt B. Kaiser11220fa2002-12-24 00:57:22 +0000264# XXX 13 Dec 2002 KBK Not used currently
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000265# def saved_change_hook(self):
266# "Extend base method - clear breaks if module is modified"
267# if not self.get_saved():
268# self.clear_file_breaks()
269# EditorWindow.saved_change_hook(self)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000270
271 def _close(self):
272 "Extend base method - clear breaks when module is closed"
273 self.clear_file_breaks()
274 EditorWindow._close(self)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000275
David Scherer7aced172000-08-15 01:13:23 +0000276
277class PyShellFileList(FileList):
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000278 "Extend base class: IDLE supports a shell and breakpoints"
David Scherer7aced172000-08-15 01:13:23 +0000279
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000280 # override FileList's class variable, instances return PyShellEditorWindow
281 # instead of EditorWindow when new edit windows are created.
David Scherer7aced172000-08-15 01:13:23 +0000282 EditorWindow = PyShellEditorWindow
283
284 pyshell = None
285
286 def open_shell(self, event=None):
287 if self.pyshell:
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000288 self.pyshell.top.wakeup()
David Scherer7aced172000-08-15 01:13:23 +0000289 else:
290 self.pyshell = PyShell(self)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000291 if self.pyshell:
292 if not self.pyshell.begin():
293 return None
David Scherer7aced172000-08-15 01:13:23 +0000294 return self.pyshell
295
296
297class ModifiedColorDelegator(ColorDelegator):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000298 "Extend base class: colorizer for the shell window itself"
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000299
Steven M. Gavab77d3432002-03-02 07:16:21 +0000300 def __init__(self):
301 ColorDelegator.__init__(self)
302 self.LoadTagDefs()
David Scherer7aced172000-08-15 01:13:23 +0000303
304 def recolorize_main(self):
305 self.tag_remove("TODO", "1.0", "iomark")
306 self.tag_add("SYNC", "1.0", "iomark")
307 ColorDelegator.recolorize_main(self)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000308
Steven M. Gavab77d3432002-03-02 07:16:21 +0000309 def LoadTagDefs(self):
310 ColorDelegator.LoadTagDefs(self)
311 theme = idleConf.GetOption('main','Theme','name')
312 self.tagdefs.update({
313 "stdin": {'background':None,'foreground':None},
314 "stdout": idleConf.GetHighlight(theme, "stdout"),
315 "stderr": idleConf.GetHighlight(theme, "stderr"),
316 "console": idleConf.GetHighlight(theme, "console"),
Steven M. Gavab77d3432002-03-02 07:16:21 +0000317 })
David Scherer7aced172000-08-15 01:13:23 +0000318
Ned Deily8b2a56b2012-05-31 09:17:29 -0700319 def removecolors(self):
320 # Don't remove shell color tags before "iomark"
321 for tag in self.tagdefs:
322 self.tag_remove(tag, "iomark", "end")
323
David Scherer7aced172000-08-15 01:13:23 +0000324class ModifiedUndoDelegator(UndoDelegator):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000325 "Extend base class: forbid insert/delete before the I/O mark"
David Scherer7aced172000-08-15 01:13:23 +0000326
327 def insert(self, index, chars, tags=None):
328 try:
329 if self.delegate.compare(index, "<", "iomark"):
330 self.delegate.bell()
331 return
332 except TclError:
333 pass
334 UndoDelegator.insert(self, index, chars, tags)
335
336 def delete(self, index1, index2=None):
337 try:
338 if self.delegate.compare(index1, "<", "iomark"):
339 self.delegate.bell()
340 return
341 except TclError:
342 pass
343 UndoDelegator.delete(self, index1, index2)
344
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000345
346class MyRPCClient(rpc.RPCClient):
347
348 def handle_EOF(self):
349 "Override the base class - just re-raise EOFError"
350 raise EOFError
351
Kurt B. Kaiser8d1f11b2003-05-26 22:20:34 +0000352
David Scherer7aced172000-08-15 01:13:23 +0000353class ModifiedInterpreter(InteractiveInterpreter):
354
355 def __init__(self, tkconsole):
356 self.tkconsole = tkconsole
357 locals = sys.modules['__main__'].__dict__
358 InteractiveInterpreter.__init__(self, locals=locals)
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000359 self.save_warnings_filters = None
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000360 self.restarting = False
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000361 self.subprocess_arglist = None
362 self.port = PORT
Ned Deily7aff4512011-10-30 20:01:35 -0700363 self.original_compiler_flags = self.compile.compiler.flags
David Scherer7aced172000-08-15 01:13:23 +0000364
Chui Tey5d2af632002-05-26 13:36:41 +0000365 rpcclt = None
Ned Deilye5cad232011-08-02 18:47:13 -0700366 rpcsubproc = None
Chui Tey5d2af632002-05-26 13:36:41 +0000367
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000368 def spawn_subprocess(self):
Florent Xiclunafd1b0932010-03-28 00:25:02 +0000369 if self.subprocess_arglist is None:
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000370 self.subprocess_arglist = self.build_subprocess_arglist()
Ned Deilye5cad232011-08-02 18:47:13 -0700371 self.rpcsubproc = subprocess.Popen(self.subprocess_arglist)
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000372
Tony Lowndsf53dec22002-12-20 04:24:43 +0000373 def build_subprocess_arglist(self):
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000374 assert (self.port!=0), (
375 "Socket should have been assigned a port number.")
Tony Lownds2398d572003-05-13 15:28:21 +0000376 w = ['-W' + s for s in sys.warnoptions]
377 # Maybe IDLE is installed and is being accessed via sys.path,
378 # or maybe it's not installed and the idle.py script is being
379 # run from the IDLE source directory.
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000380 del_exitf = idleConf.GetOption('main', 'General', 'delete-exitfunc',
381 default=False, type='bool')
Tony Lownds2398d572003-05-13 15:28:21 +0000382 if __name__ == 'idlelib.PyShell':
Walter Dörwald70a6b492004-02-12 17:35:32 +0000383 command = "__import__('idlelib.run').run.main(%r)" % (del_exitf,)
Tony Lowndsf2324b92002-09-29 00:34:10 +0000384 else:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000385 command = "__import__('run').main(%r)" % (del_exitf,)
Ned Deilye5cad232011-08-02 18:47:13 -0700386 return [sys.executable] + w + ["-c", command, str(self.port)]
Tony Lowndsf2324b92002-09-29 00:34:10 +0000387
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000388 def start_subprocess(self):
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000389 addr = (HOST, self.port)
390 # GUI makes several attempts to acquire socket, listens for connection
Kurt B. Kaiser5db48432003-05-15 03:40:51 +0000391 for i in range(3):
Chui Tey5d2af632002-05-26 13:36:41 +0000392 time.sleep(i)
393 try:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000394 self.rpcclt = MyRPCClient(addr)
Chui Tey5d2af632002-05-26 13:36:41 +0000395 break
Guido van Rossumb940e112007-01-10 16:19:56 +0000396 except socket.error as err:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000397 pass
Chui Tey5d2af632002-05-26 13:36:41 +0000398 else:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000399 self.display_port_binding_error()
400 return None
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000401 # if PORT was 0, system will assign an 'ephemeral' port. Find it out:
402 self.port = self.rpcclt.listening_sock.getsockname()[1]
403 # if PORT was not 0, probably working with a remote execution server
404 if PORT != 0:
405 # To allow reconnection within the 2MSL wait (cf. Stevens TCP
406 # V1, 18.6), set SO_REUSEADDR. Note that this can be problematic
407 # on Windows since the implementation allows two active sockets on
408 # the same address!
409 self.rpcclt.listening_sock.setsockopt(socket.SOL_SOCKET,
410 socket.SO_REUSEADDR, 1)
411 self.spawn_subprocess()
412 #time.sleep(20) # test to simulate GUI not accepting connection
Kurt B. Kaiserb4179362002-07-26 00:06:42 +0000413 # Accept the connection from the Python execution server
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000414 self.rpcclt.listening_sock.settimeout(10)
415 try:
416 self.rpcclt.accept()
Guido van Rossumb940e112007-01-10 16:19:56 +0000417 except socket.timeout as err:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000418 self.display_no_subprocess_error()
419 return None
Martin v. Löwisc882b7c2012-07-25 10:47:20 +0200420 # Can't regiter self.tkconsole.stdin, since run.py wants to
421 # call non-TextIO methods on it (such as getvar)
422 # XXX should be renamed to "console"
Kurt B. Kaiser969de452002-06-12 03:28:57 +0000423 self.rpcclt.register("stdin", self.tkconsole)
424 self.rpcclt.register("stdout", self.tkconsole.stdout)
425 self.rpcclt.register("stderr", self.tkconsole.stderr)
Chui Tey5d2af632002-05-26 13:36:41 +0000426 self.rpcclt.register("flist", self.tkconsole.flist)
Kurt B. Kaiser8cd0def2003-01-31 05:06:43 +0000427 self.rpcclt.register("linecache", linecache)
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000428 self.rpcclt.register("interp", self)
Terry Jan Reedyda4c4672012-01-31 02:26:32 -0500429 self.transfer_path(with_cwd=True)
Chui Tey5d2af632002-05-26 13:36:41 +0000430 self.poll_subprocess()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000431 return self.rpcclt
Chui Tey5d2af632002-05-26 13:36:41 +0000432
Terry Jan Reedyda4c4672012-01-31 02:26:32 -0500433 def restart_subprocess(self, with_cwd=False):
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000434 if self.restarting:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000435 return self.rpcclt
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000436 self.restarting = True
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000437 # close only the subprocess debugger
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000438 debug = self.getdebugger()
439 if debug:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000440 try:
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000441 # Only close subprocess debugger, don't unregister gui_adap!
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000442 RemoteDebugger.close_subprocess_debugger(self.rpcclt)
443 except:
444 pass
445 # Kill subprocess, spawn a new one, accept connection.
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000446 self.rpcclt.close()
Ned Deilye5cad232011-08-02 18:47:13 -0700447 self.terminate_subprocess()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000448 console = self.tkconsole
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000449 was_executing = console.executing
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000450 console.executing = False
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000451 self.spawn_subprocess()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000452 try:
453 self.rpcclt.accept()
Guido van Rossumb940e112007-01-10 16:19:56 +0000454 except socket.timeout as err:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000455 self.display_no_subprocess_error()
456 return None
Terry Jan Reedyda4c4672012-01-31 02:26:32 -0500457 self.transfer_path(with_cwd=with_cwd)
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000458 # annotate restart in shell window and mark it
Kurt B. Kaiser4cc5ef52003-01-22 00:23:23 +0000459 console.text.delete("iomark", "end-1c")
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000460 if was_executing:
461 console.write('\n')
462 console.showprompt()
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000463 halfbar = ((int(console.width) - 16) // 2) * '='
464 console.write(halfbar + ' RESTART ' + halfbar)
465 console.text.mark_set("restart", "end-1c")
466 console.text.mark_gravity("restart", "left")
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000467 console.showprompt()
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000468 # restart subprocess debugger
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000469 if debug:
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000470 # Restarted debugger connects to current instance of debug GUI
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000471 gui = RemoteDebugger.restart_subprocess_debugger(self.rpcclt)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000472 # reload remote debugger breakpoints for all PyShellEditWindows
473 debug.load_breakpoints()
Ned Deily7aff4512011-10-30 20:01:35 -0700474 self.compile.compiler.flags = self.original_compiler_flags
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000475 self.restarting = False
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000476 return self.rpcclt
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000477
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000478 def __request_interrupt(self):
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000479 self.rpcclt.remotecall("exec", "interrupt_the_server", (), {})
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000480
481 def interrupt_subprocess(self):
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000482 threading.Thread(target=self.__request_interrupt).start()
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000483
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000484 def kill_subprocess(self):
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000485 try:
Ned Deily55f87572011-11-05 22:36:44 -0700486 self.rpcclt.listening_sock.close()
487 except AttributeError: # no socket
488 pass
489 try:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000490 self.rpcclt.close()
491 except AttributeError: # no socket
492 pass
Ned Deilye5cad232011-08-02 18:47:13 -0700493 self.terminate_subprocess()
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000494 self.tkconsole.executing = False
495 self.rpcclt = None
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000496
Ned Deilye5cad232011-08-02 18:47:13 -0700497 def terminate_subprocess(self):
498 "Make sure subprocess is terminated"
499 try:
500 self.rpcsubproc.kill()
501 except OSError:
502 # process already terminated
503 return
504 else:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000505 try:
Ned Deilye5cad232011-08-02 18:47:13 -0700506 self.rpcsubproc.wait()
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000507 except OSError:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000508 return
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000509
Terry Jan Reedyda4c4672012-01-31 02:26:32 -0500510 def transfer_path(self, with_cwd=False):
511 if with_cwd: # Issue 13506
512 path = [''] # include Current Working Directory
513 path.extend(sys.path)
514 else:
515 path = sys.path
Terry Jan Reedy4d82ade2012-01-31 02:57:29 -0500516
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000517 self.runcommand("""if 1:
518 import sys as _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +0000519 _sys.path = %r
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000520 del _sys
Terry Jan Reedyda4c4672012-01-31 02:26:32 -0500521 \n""" % (path,))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000522
Chui Tey5d2af632002-05-26 13:36:41 +0000523 active_seq = None
524
525 def poll_subprocess(self):
526 clt = self.rpcclt
527 if clt is None:
528 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000529 try:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000530 response = clt.pollresponse(self.active_seq, wait=0.05)
531 except (EOFError, IOError, KeyboardInterrupt):
532 # lost connection or subprocess terminated itself, restart
533 # [the KBI is from rpc.SocketIO.handle_EOF()]
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000534 if self.tkconsole.closing:
535 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000536 response = None
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000537 self.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000538 if response:
539 self.tkconsole.resetoutput()
540 self.active_seq = None
541 how, what = response
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000542 console = self.tkconsole.console
Chui Tey5d2af632002-05-26 13:36:41 +0000543 if how == "OK":
544 if what is not None:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000545 print(repr(what), file=console)
Chui Tey5d2af632002-05-26 13:36:41 +0000546 elif how == "EXCEPTION":
Chui Tey5d2af632002-05-26 13:36:41 +0000547 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
548 self.remote_stack_viewer()
549 elif how == "ERROR":
Kurt B. Kaiser0930c432002-12-06 21:45:24 +0000550 errmsg = "PyShell.ModifiedInterpreter: Subprocess ERROR:\n"
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000551 print(errmsg, what, file=sys.__stderr__)
552 print(errmsg, what, file=console)
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000553 # we received a response to the currently active seq number:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000554 try:
555 self.tkconsole.endexecuting()
556 except AttributeError: # shell may have closed
557 pass
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000558 # Reschedule myself
559 if not self.tkconsole.closing:
560 self.tkconsole.text.after(self.tkconsole.pollinterval,
561 self.poll_subprocess)
Chui Tey5d2af632002-05-26 13:36:41 +0000562
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000563 debugger = None
564
565 def setdebugger(self, debugger):
566 self.debugger = debugger
567
568 def getdebugger(self):
569 return self.debugger
570
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000571 def open_remote_stack_viewer(self):
572 """Initiate the remote stack viewer from a separate thread.
573
574 This method is called from the subprocess, and by returning from this
575 method we allow the subprocess to unblock. After a bit the shell
576 requests the subprocess to open the remote stack viewer which returns a
Ezio Melotti60861182010-07-23 16:48:22 +0000577 static object looking at the last exception. It is queried through
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000578 the RPC mechanism.
579
580 """
581 self.tkconsole.text.after(300, self.remote_stack_viewer)
582 return
583
Chui Tey5d2af632002-05-26 13:36:41 +0000584 def remote_stack_viewer(self):
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000585 from idlelib import RemoteObjectBrowser
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000586 oid = self.rpcclt.remotequeue("exec", "stackviewer", ("flist",), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000587 if oid is None:
588 self.tkconsole.root.bell()
589 return
590 item = RemoteObjectBrowser.StubObjectTreeItem(self.rpcclt, oid)
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000591 from idlelib.TreeWidget import ScrolledCanvas, TreeNode
Chui Tey5d2af632002-05-26 13:36:41 +0000592 top = Toplevel(self.tkconsole.root)
Kurt B. Kaiser73360a32004-03-08 18:15:31 +0000593 theme = idleConf.GetOption('main','Theme','name')
594 background = idleConf.GetHighlight(theme, 'normal')['background']
595 sc = ScrolledCanvas(top, bg=background, highlightthickness=0)
Chui Tey5d2af632002-05-26 13:36:41 +0000596 sc.frame.pack(expand=1, fill="both")
597 node = TreeNode(sc.canvas, None, item)
598 node.expand()
599 # XXX Should GC the remote tree when closing the window
600
David Scherer7aced172000-08-15 01:13:23 +0000601 gid = 0
602
603 def execsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000604 "Like runsource() but assumes complete exec source"
David Scherer7aced172000-08-15 01:13:23 +0000605 filename = self.stuffsource(source)
606 self.execfile(filename, source)
607
608 def execfile(self, filename, source=None):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000609 "Execute an existing file"
David Scherer7aced172000-08-15 01:13:23 +0000610 if source is None:
Victor Stinner979482a2011-09-02 01:00:40 +0200611 with tokenize.open(filename) as fp:
Victor Stinner85c67722011-09-02 00:57:04 +0200612 source = fp.read()
David Scherer7aced172000-08-15 01:13:23 +0000613 try:
614 code = compile(source, filename, "exec")
615 except (OverflowError, SyntaxError):
616 self.tkconsole.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000617 tkerr = self.tkconsole.stderr
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000618 print('*** Error in script or command!\n', file=tkerr)
619 print('Traceback (most recent call last):', file=tkerr)
David Scherer7aced172000-08-15 01:13:23 +0000620 InteractiveInterpreter.showsyntaxerror(self, filename)
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000621 self.tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000622 else:
623 self.runcode(code)
624
625 def runsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000626 "Extend base class method: Stuff the source in the line cache first"
David Scherer7aced172000-08-15 01:13:23 +0000627 filename = self.stuffsource(source)
628 self.more = 0
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000629 self.save_warnings_filters = warnings.filters[:]
630 warnings.filterwarnings(action="error", category=SyntaxWarning)
Martin v. Löwis98ff8982007-08-13 06:03:15 +0000631 # at the moment, InteractiveInterpreter expects str
632 assert isinstance(source, str)
633 #if isinstance(source, str):
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000634 # from idlelib import IOBinding
Martin v. Löwis98ff8982007-08-13 06:03:15 +0000635 # try:
636 # source = source.encode(IOBinding.encoding)
637 # except UnicodeError:
638 # self.tkconsole.resetoutput()
639 # self.write("Unsupported characters in input\n")
640 # return
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000641 try:
Kurt B. Kaiser935ea9a2005-05-10 03:44:24 +0000642 # InteractiveInterpreter.runsource() calls its runcode() method,
643 # which is overridden (see below)
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000644 return InteractiveInterpreter.runsource(self, source, filename)
645 finally:
646 if self.save_warnings_filters is not None:
647 warnings.filters[:] = self.save_warnings_filters
648 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000649
650 def stuffsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000651 "Stuff source in the filename cache"
David Scherer7aced172000-08-15 01:13:23 +0000652 filename = "<pyshell#%d>" % self.gid
653 self.gid = self.gid + 1
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000654 lines = source.split("\n")
David Scherer7aced172000-08-15 01:13:23 +0000655 linecache.cache[filename] = len(source)+1, 0, lines, filename
656 return filename
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000657
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000658 def prepend_syspath(self, filename):
659 "Prepend sys.path with file's directory if not already included"
660 self.runcommand("""if 1:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000661 _filename = %r
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000662 import sys as _sys
663 from os.path import dirname as _dirname
664 _dir = _dirname(_filename)
665 if not _dir in _sys.path:
666 _sys.path.insert(0, _dir)
667 del _filename, _sys, _dirname, _dir
Walter Dörwald70a6b492004-02-12 17:35:32 +0000668 \n""" % (filename,))
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000669
David Scherer7aced172000-08-15 01:13:23 +0000670 def showsyntaxerror(self, filename=None):
Guido van Rossum33d26892007-08-05 15:29:28 +0000671 """Override Interactive Interpreter method: Use Colorizing
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000672
673 Color the offending position instead of printing it and pointing at it
674 with a caret.
675
676 """
Guido van Rossum33d26892007-08-05 15:29:28 +0000677 tkconsole = self.tkconsole
678 text = tkconsole.text
679 text.tag_remove("ERROR", "1.0", "end")
David Scherer7aced172000-08-15 01:13:23 +0000680 type, value, tb = sys.exc_info()
Ned Deily79746422011-09-14 14:49:14 -0700681 msg = getattr(value, 'msg', '') or value or "<no detail available>"
682 lineno = getattr(value, 'lineno', '') or 1
683 offset = getattr(value, 'offset', '') or 0
Guido van Rossum33d26892007-08-05 15:29:28 +0000684 if offset == 0:
685 lineno += 1 #mark end of offending line
686 if lineno == 1:
687 pos = "iomark + %d chars" % (offset-1)
David Scherer7aced172000-08-15 01:13:23 +0000688 else:
Guido van Rossum33d26892007-08-05 15:29:28 +0000689 pos = "iomark linestart + %d lines + %d chars" % \
690 (lineno-1, offset-1)
691 tkconsole.colorize_syntax_error(text, pos)
692 tkconsole.resetoutput()
693 self.write("SyntaxError: %s\n" % msg)
694 tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000695
696 def showtraceback(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000697 "Extend base class method to reset output properly"
David Scherer7aced172000-08-15 01:13:23 +0000698 self.tkconsole.resetoutput()
699 self.checklinecache()
700 InteractiveInterpreter.showtraceback(self)
Chui Tey5d2af632002-05-26 13:36:41 +0000701 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
702 self.tkconsole.open_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +0000703
704 def checklinecache(self):
705 c = linecache.cache
Guido van Rossum36e0a922007-07-20 04:05:57 +0000706 for key in list(c.keys()):
David Scherer7aced172000-08-15 01:13:23 +0000707 if key[:1] + key[-1:] != "<>":
708 del c[key]
709
Chui Tey5d2af632002-05-26 13:36:41 +0000710 def runcommand(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000711 "Run the code without invoking the debugger"
Chui Tey5d2af632002-05-26 13:36:41 +0000712 # The code better not raise an exception!
713 if self.tkconsole.executing:
Neal Norwitzf4c4f112002-11-30 18:49:10 +0000714 self.display_executing_dialog()
Chui Tey5d2af632002-05-26 13:36:41 +0000715 return 0
716 if self.rpcclt:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000717 self.rpcclt.remotequeue("exec", "runcode", (code,), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000718 else:
Georg Brandl7cae87c2006-09-06 06:51:57 +0000719 exec(code, self.locals)
Chui Tey5d2af632002-05-26 13:36:41 +0000720 return 1
721
David Scherer7aced172000-08-15 01:13:23 +0000722 def runcode(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000723 "Override base class method"
Chui Tey5d2af632002-05-26 13:36:41 +0000724 if self.tkconsole.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000725 self.interp.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000726 self.checklinecache()
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000727 if self.save_warnings_filters is not None:
728 warnings.filters[:] = self.save_warnings_filters
729 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000730 debugger = self.debugger
731 try:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000732 self.tkconsole.beginexecuting()
Thomas Wouterscf297e42007-02-23 15:07:44 +0000733 if not debugger and self.rpcclt is not None:
734 self.active_seq = self.rpcclt.asyncqueue("exec", "runcode",
735 (code,), {})
736 elif debugger:
737 debugger.run(code, self.locals)
738 else:
739 exec(code, self.locals)
740 except SystemExit:
741 if not self.tkconsole.closing:
742 if tkMessageBox.askyesno(
743 "Exit?",
744 "Do you want to exit altogether?",
745 default="yes",
746 master=self.tkconsole.text):
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000747 raise
Thomas Wouterscf297e42007-02-23 15:07:44 +0000748 else:
Guido van Rossum5dc0d972007-02-25 22:37:36 +0000749 self.showtraceback()
Thomas Wouterscf297e42007-02-23 15:07:44 +0000750 else:
751 raise
752 except:
753 if use_subprocess:
754 print("IDLE internal error in runcode()",
755 file=self.tkconsole.stderr)
David Scherer7aced172000-08-15 01:13:23 +0000756 self.showtraceback()
Thomas Wouterscf297e42007-02-23 15:07:44 +0000757 self.tkconsole.endexecuting()
758 else:
759 if self.tkconsole.canceled:
760 self.tkconsole.canceled = False
761 print("KeyboardInterrupt", file=self.tkconsole.stderr)
762 else:
763 self.showtraceback()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000764 finally:
765 if not use_subprocess:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000766 try:
767 self.tkconsole.endexecuting()
768 except AttributeError: # shell may have closed
769 pass
David Scherer7aced172000-08-15 01:13:23 +0000770
771 def write(self, s):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000772 "Override base class method"
Martin v. Löwis30d5e6c2012-07-25 11:32:26 +0200773 return self.tkconsole.stderr.write(s)
David Scherer7aced172000-08-15 01:13:23 +0000774
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000775 def display_port_binding_error(self):
776 tkMessageBox.showerror(
777 "Port Binding Error",
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000778 "IDLE can't bind to a TCP/IP port, which is necessary to "
779 "communicate with its Python execution server. This might be "
780 "because no networking is installed on this computer. "
781 "Run IDLE with the -n command line switch to start without a "
782 "subprocess and refer to Help/IDLE Help 'Running without a "
783 "subprocess' for further details.",
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000784 master=self.tkconsole.text)
785
786 def display_no_subprocess_error(self):
787 tkMessageBox.showerror(
788 "Subprocess Startup Error",
789 "IDLE's subprocess didn't make connection. Either IDLE can't "
790 "start a subprocess or personal firewall software is blocking "
791 "the connection.",
792 master=self.tkconsole.text)
793
794 def display_executing_dialog(self):
795 tkMessageBox.showerror(
796 "Already executing",
797 "The Python Shell window is already executing a command; "
798 "please wait until it is finished.",
799 master=self.tkconsole.text)
800
801
David Scherer7aced172000-08-15 01:13:23 +0000802class PyShell(OutputWindow):
803
804 shell_title = "Python Shell"
805
806 # Override classes
807 ColorDelegator = ModifiedColorDelegator
808 UndoDelegator = ModifiedUndoDelegator
809
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000810 # Override menus
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000811 menu_specs = [
812 ("file", "_File"),
813 ("edit", "_Edit"),
Kurt B. Kaiser4cc5ef52003-01-22 00:23:23 +0000814 ("debug", "_Debug"),
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000815 ("options", "_Options"),
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000816 ("windows", "_Windows"),
817 ("help", "_Help"),
818 ]
David Scherer7aced172000-08-15 01:13:23 +0000819
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000820 if macosxSupport.runningAsOSXApp():
821 del menu_specs[-3]
822 menu_specs[-2] = ("windows", "_Window")
823
824
David Scherer7aced172000-08-15 01:13:23 +0000825 # New classes
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000826 from idlelib.IdleHistory import History
David Scherer7aced172000-08-15 01:13:23 +0000827
828 def __init__(self, flist=None):
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000829 if use_subprocess:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000830 ms = self.menu_specs
831 if ms[2][0] != "shell":
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000832 ms.insert(2, ("shell", "She_ll"))
David Scherer7aced172000-08-15 01:13:23 +0000833 self.interp = ModifiedInterpreter(self)
834 if flist is None:
835 root = Tk()
836 fixwordbreaks(root)
837 root.withdraw()
838 flist = PyShellFileList(root)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000839 #
David Scherer7aced172000-08-15 01:13:23 +0000840 OutputWindow.__init__(self, flist, None, None)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000841 #
Kurt B. Kaiser6af44982005-01-19 00:22:59 +0000842## self.config(usetabs=1, indentwidth=8, context_use_ps1=1)
843 self.usetabs = True
844 # indentwidth must be 8 when using tabs. See note in EditorWindow:
845 self.indentwidth = 8
846 self.context_use_ps1 = True
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000847 #
David Scherer7aced172000-08-15 01:13:23 +0000848 text = self.text
849 text.configure(wrap="char")
850 text.bind("<<newline-and-indent>>", self.enter_callback)
851 text.bind("<<plain-newline-and-indent>>", self.linefeed_callback)
852 text.bind("<<interrupt-execution>>", self.cancel_callback)
David Scherer7aced172000-08-15 01:13:23 +0000853 text.bind("<<end-of-file>>", self.eof_callback)
854 text.bind("<<open-stack-viewer>>", self.open_stack_viewer)
Kurt B. Kaiser57bfe5d2003-05-10 00:09:52 +0000855 text.bind("<<toggle-debugger>>", self.toggle_debugger)
David Scherer7aced172000-08-15 01:13:23 +0000856 text.bind("<<toggle-jit-stack-viewer>>", self.toggle_jit_stack_viewer)
Kurt B. Kaiser8a78cad2007-12-13 03:38:16 +0000857 self.color = color = self.ColorDelegator()
858 self.per.insertfilter(color)
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000859 if use_subprocess:
860 text.bind("<<view-restart>>", self.view_restart_mark)
861 text.bind("<<restart-shell>>", self.restart_shell)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000862 #
David Scherer7aced172000-08-15 01:13:23 +0000863 self.save_stdout = sys.stdout
864 self.save_stderr = sys.stderr
865 self.save_stdin = sys.stdin
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000866 from idlelib import IOBinding
Martin v. Löwisc882b7c2012-07-25 10:47:20 +0200867 self.stdin = PseudoInputFile(self)
Martin v. Löwisbcc651a2003-06-22 07:52:56 +0000868 self.stdout = PseudoFile(self, "stdout", IOBinding.encoding)
869 self.stderr = PseudoFile(self, "stderr", IOBinding.encoding)
870 self.console = PseudoFile(self, "console", IOBinding.encoding)
Chui Tey5d2af632002-05-26 13:36:41 +0000871 if not use_subprocess:
872 sys.stdout = self.stdout
Kurt B. Kaiser7cec2522007-08-31 04:15:13 +0000873 sys.stderr = self.stderr
Martin v. Löwisc882b7c2012-07-25 10:47:20 +0200874 sys.stdin = self.stdin
Kurt B. Kaiserf609a342007-12-28 03:57:56 +0000875 try:
876 # page help() text to shell.
877 import pydoc # import must be done here to capture i/o rebinding.
878 # XXX KBK 27Dec07 use a textView someday, but must work w/o subproc
879 pydoc.pager = pydoc.plainpager
880 except:
881 sys.stderr = sys.__stderr__
882 raise
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000883 #
David Scherer7aced172000-08-15 01:13:23 +0000884 self.history = self.History(self.text)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000885 #
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000886 self.pollinterval = 50 # millisec
Chui Tey5d2af632002-05-26 13:36:41 +0000887
Kurt B. Kaiser4d5bc602004-06-06 01:29:22 +0000888 def get_standard_extension_names(self):
889 return idleConf.GetExtensions(shell_only=True)
890
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000891 reading = False
892 executing = False
893 canceled = False
894 endoffile = False
895 closing = False
David Scherer7aced172000-08-15 01:13:23 +0000896
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +0000897 def set_warning_stream(self, stream):
Skip Montanarod9161422004-07-06 21:53:27 +0000898 global warning_stream
899 warning_stream = stream
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +0000900
901 def get_warning_stream(self):
902 return warning_stream
903
David Scherer7aced172000-08-15 01:13:23 +0000904 def toggle_debugger(self, event=None):
905 if self.executing:
906 tkMessageBox.showerror("Don't debug now",
907 "You can only toggle the debugger when idle",
908 master=self.text)
909 self.set_debugger_indicator()
910 return "break"
911 else:
912 db = self.interp.getdebugger()
913 if db:
914 self.close_debugger()
915 else:
916 self.open_debugger()
917
918 def set_debugger_indicator(self):
919 db = self.interp.getdebugger()
920 self.setvar("<<toggle-debugger>>", not not db)
921
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000922 def toggle_jit_stack_viewer(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +0000923 pass # All we need is the variable
924
925 def close_debugger(self):
926 db = self.interp.getdebugger()
927 if db:
928 self.interp.setdebugger(None)
929 db.close()
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000930 if self.interp.rpcclt:
931 RemoteDebugger.close_remote_debugger(self.interp.rpcclt)
David Scherer7aced172000-08-15 01:13:23 +0000932 self.resetoutput()
933 self.console.write("[DEBUG OFF]\n")
934 sys.ps1 = ">>> "
935 self.showprompt()
936 self.set_debugger_indicator()
937
938 def open_debugger(self):
Chui Tey5d2af632002-05-26 13:36:41 +0000939 if self.interp.rpcclt:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000940 dbg_gui = RemoteDebugger.start_remote_debugger(self.interp.rpcclt,
941 self)
942 else:
943 dbg_gui = Debugger.Debugger(self)
944 self.interp.setdebugger(dbg_gui)
945 dbg_gui.load_breakpoints()
Chui Tey5d2af632002-05-26 13:36:41 +0000946 sys.ps1 = "[DEBUG ON]\n>>> "
947 self.showprompt()
948 self.set_debugger_indicator()
949
David Scherer7aced172000-08-15 01:13:23 +0000950 def beginexecuting(self):
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000951 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +0000952 self.resetoutput()
953 self.executing = 1
David Scherer7aced172000-08-15 01:13:23 +0000954
955 def endexecuting(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000956 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +0000957 self.executing = 0
958 self.canceled = 0
Chui Tey5d2af632002-05-26 13:36:41 +0000959 self.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000960
961 def close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000962 "Extend EditorWindow.close()"
David Scherer7aced172000-08-15 01:13:23 +0000963 if self.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000964 response = tkMessageBox.askokcancel(
David Scherer7aced172000-08-15 01:13:23 +0000965 "Kill?",
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000966 "The program is still running!\n Do you want to kill it?",
David Scherer7aced172000-08-15 01:13:23 +0000967 default="ok",
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000968 parent=self.text)
Benjamin Peterson2a691a82008-03-31 01:51:45 +0000969 if response is False:
David Scherer7aced172000-08-15 01:13:23 +0000970 return "cancel"
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +0000971 if self.reading:
972 self.top.quit()
973 self.canceled = True
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000974 self.closing = True
975 # Wait for poll_subprocess() rescheduling to stop
976 self.text.after(2 * self.pollinterval, self.close2)
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000977
978 def close2(self):
979 return EditorWindow.close(self)
David Scherer7aced172000-08-15 01:13:23 +0000980
981 def _close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000982 "Extend EditorWindow._close(), shut down debugger and execution server"
David Scherer7aced172000-08-15 01:13:23 +0000983 self.close_debugger()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000984 if use_subprocess:
985 self.interp.kill_subprocess()
David Scherer7aced172000-08-15 01:13:23 +0000986 # Restore std streams
987 sys.stdout = self.save_stdout
988 sys.stderr = self.save_stderr
989 sys.stdin = self.save_stdin
990 # Break cycles
991 self.interp = None
992 self.console = None
David Scherer7aced172000-08-15 01:13:23 +0000993 self.flist.pyshell = None
994 self.history = None
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000995 EditorWindow._close(self)
David Scherer7aced172000-08-15 01:13:23 +0000996
997 def ispythonsource(self, filename):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000998 "Override EditorWindow method: never remove the colorizer"
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000999 return True
David Scherer7aced172000-08-15 01:13:23 +00001000
1001 def short_title(self):
1002 return self.shell_title
1003
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +00001004 COPYRIGHT = \
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001005 'Type "copyright", "credits" or "license()" for more information.'
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +00001006
David Scherer7aced172000-08-15 01:13:23 +00001007 def begin(self):
Kurt B. Kaiser7378df72007-08-11 04:20:51 +00001008 self.text.mark_set("iomark", "insert")
David Scherer7aced172000-08-15 01:13:23 +00001009 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001010 if use_subprocess:
1011 nosub = ''
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001012 client = self.interp.start_subprocess()
1013 if not client:
1014 self.close()
Kurt B. Kaiser76637292004-01-21 22:10:01 +00001015 return False
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001016 else:
Andrew Svetlov9b1e59a2012-10-05 22:12:44 +03001017 nosub = ("==== No Subprocess ====\n\n" +
Andrew Svetlov64478ac2012-10-05 22:16:55 +03001018 "WARNING: Running IDLE without a Subprocess is deprecated\n" +
Andrew Svetlov9b1e59a2012-10-05 22:12:44 +03001019 "and will be removed in a later version. See Help/IDLE Help\n" +
1020 "for details.\n\n")
Andrew Svetlovcd49d532012-03-25 11:43:02 +03001021 sys.displayhook = rpc.displayhook
1022
Raymond Hettingera2a8e8b2009-01-27 00:28:36 +00001023 self.write("Python %s on %s\n%s\n%s" %
1024 (sys.version, sys.platform, self.COPYRIGHT, nosub))
David Scherer7aced172000-08-15 01:13:23 +00001025 self.showprompt()
Georg Brandl14fc4272008-05-17 18:39:55 +00001026 import tkinter
1027 tkinter._default_root = None # 03Jan04 KBK What's this?
Kurt B. Kaiser76637292004-01-21 22:10:01 +00001028 return True
David Scherer7aced172000-08-15 01:13:23 +00001029
1030 def readline(self):
1031 save = self.reading
1032 try:
1033 self.reading = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001034 self.top.mainloop() # nested mainloop()
David Scherer7aced172000-08-15 01:13:23 +00001035 finally:
1036 self.reading = save
1037 line = self.text.get("iomark", "end-1c")
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001038 if len(line) == 0: # may be EOF if we quit our mainloop with Ctrl-C
1039 line = "\n"
David Scherer7aced172000-08-15 01:13:23 +00001040 self.resetoutput()
1041 if self.canceled:
1042 self.canceled = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001043 if not use_subprocess:
1044 raise KeyboardInterrupt
David Scherer7aced172000-08-15 01:13:23 +00001045 if self.endoffile:
1046 self.endoffile = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001047 line = ""
David Scherer7aced172000-08-15 01:13:23 +00001048 return line
1049
1050 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001051 return True
David Scherer7aced172000-08-15 01:13:23 +00001052
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001053 def cancel_callback(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +00001054 try:
1055 if self.text.compare("sel.first", "!=", "sel.last"):
1056 return # Active selection -- always use default binding
1057 except:
1058 pass
1059 if not (self.executing or self.reading):
1060 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001061 self.interp.write("KeyboardInterrupt\n")
David Scherer7aced172000-08-15 01:13:23 +00001062 self.showprompt()
1063 return "break"
1064 self.endoffile = 0
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001065 self.canceled = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001066 if (self.executing and self.interp.rpcclt):
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +00001067 if self.interp.getdebugger():
1068 self.interp.restart_subprocess()
1069 else:
1070 self.interp.interrupt_subprocess()
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001071 if self.reading:
1072 self.top.quit() # exit the nested mainloop() in readline()
David Scherer7aced172000-08-15 01:13:23 +00001073 return "break"
1074
1075 def eof_callback(self, event):
1076 if self.executing and not self.reading:
1077 return # Let the default binding (delete next char) take over
1078 if not (self.text.compare("iomark", "==", "insert") and
1079 self.text.compare("insert", "==", "end-1c")):
1080 return # Let the default binding (delete next char) take over
1081 if not self.executing:
David Scherer7aced172000-08-15 01:13:23 +00001082 self.resetoutput()
1083 self.close()
1084 else:
1085 self.canceled = 0
1086 self.endoffile = 1
1087 self.top.quit()
1088 return "break"
1089
David Scherer7aced172000-08-15 01:13:23 +00001090 def linefeed_callback(self, event):
1091 # Insert a linefeed without entering anything (still autoindented)
1092 if self.reading:
1093 self.text.insert("insert", "\n")
1094 self.text.see("insert")
1095 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001096 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001097 return "break"
1098
1099 def enter_callback(self, event):
1100 if self.executing and not self.reading:
1101 return # Let the default binding (insert '\n') take over
1102 # If some text is selected, recall the selection
1103 # (but only if this before the I/O mark)
1104 try:
1105 sel = self.text.get("sel.first", "sel.last")
1106 if sel:
1107 if self.text.compare("sel.last", "<=", "iomark"):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001108 self.recall(sel, event)
David Scherer7aced172000-08-15 01:13:23 +00001109 return "break"
1110 except:
1111 pass
1112 # If we're strictly before the line containing iomark, recall
1113 # the current line, less a leading prompt, less leading or
1114 # trailing whitespace
1115 if self.text.compare("insert", "<", "iomark linestart"):
1116 # Check if there's a relevant stdin range -- if so, use it
1117 prev = self.text.tag_prevrange("stdin", "insert")
1118 if prev and self.text.compare("insert", "<", prev[1]):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001119 self.recall(self.text.get(prev[0], prev[1]), event)
David Scherer7aced172000-08-15 01:13:23 +00001120 return "break"
1121 next = self.text.tag_nextrange("stdin", "insert")
1122 if next and self.text.compare("insert lineend", ">=", next[0]):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001123 self.recall(self.text.get(next[0], next[1]), event)
David Scherer7aced172000-08-15 01:13:23 +00001124 return "break"
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001125 # No stdin mark -- just get the current line, less any prompt
Kurt B. Kaiserb1754452005-11-18 22:05:48 +00001126 indices = self.text.tag_nextrange("console", "insert linestart")
1127 if indices and \
1128 self.text.compare(indices[0], "<=", "insert linestart"):
1129 self.recall(self.text.get(indices[1], "insert lineend"), event)
1130 else:
1131 self.recall(self.text.get("insert linestart", "insert lineend"), event)
David Scherer7aced172000-08-15 01:13:23 +00001132 return "break"
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001133 # If we're between the beginning of the line and the iomark, i.e.
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001134 # in the prompt area, move to the end of the prompt
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001135 if self.text.compare("insert", "<", "iomark"):
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001136 self.text.mark_set("insert", "iomark")
David Scherer7aced172000-08-15 01:13:23 +00001137 # If we're in the current input and there's only whitespace
1138 # beyond the cursor, erase that whitespace first
1139 s = self.text.get("insert", "end-1c")
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001140 if s and not s.strip():
David Scherer7aced172000-08-15 01:13:23 +00001141 self.text.delete("insert", "end-1c")
1142 # If we're in the current input before its last line,
1143 # insert a newline right at the insert point
1144 if self.text.compare("insert", "<", "end-1c linestart"):
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001145 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001146 return "break"
1147 # We're in the last line; append a newline and submit it
1148 self.text.mark_set("insert", "end-1c")
1149 if self.reading:
1150 self.text.insert("insert", "\n")
1151 self.text.see("insert")
1152 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001153 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001154 self.text.tag_add("stdin", "iomark", "end-1c")
1155 self.text.update_idletasks()
1156 if self.reading:
Neal Norwitzce96f692006-03-17 06:49:51 +00001157 self.top.quit() # Break out of recursive mainloop()
David Scherer7aced172000-08-15 01:13:23 +00001158 else:
1159 self.runit()
1160 return "break"
1161
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001162 def recall(self, s, event):
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001163 # remove leading and trailing empty or whitespace lines
1164 s = re.sub(r'^\s*\n', '' , s)
1165 s = re.sub(r'\n\s*$', '', s)
1166 lines = s.split('\n')
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001167 self.text.undo_block_start()
1168 try:
1169 self.text.tag_remove("sel", "1.0", "end")
1170 self.text.mark_set("insert", "end-1c")
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001171 prefix = self.text.get("insert linestart", "insert")
1172 if prefix.rstrip().endswith(':'):
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001173 self.newline_and_indent_event(event)
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001174 prefix = self.text.get("insert linestart", "insert")
1175 self.text.insert("insert", lines[0].strip())
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001176 if len(lines) > 1:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001177 orig_base_indent = re.search(r'^([ \t]*)', lines[0]).group(0)
1178 new_base_indent = re.search(r'^([ \t]*)', prefix).group(0)
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001179 for line in lines[1:]:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001180 if line.startswith(orig_base_indent):
1181 # replace orig base indentation with new indentation
1182 line = new_base_indent + line[len(orig_base_indent):]
1183 self.text.insert('insert', '\n'+line.rstrip())
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001184 finally:
1185 self.text.see("insert")
1186 self.text.undo_block_stop()
David Scherer7aced172000-08-15 01:13:23 +00001187
1188 def runit(self):
1189 line = self.text.get("iomark", "end-1c")
1190 # Strip off last newline and surrounding whitespace.
1191 # (To allow you to hit return twice to end a statement.)
1192 i = len(line)
1193 while i > 0 and line[i-1] in " \t":
1194 i = i-1
1195 if i > 0 and line[i-1] == "\n":
1196 i = i-1
1197 while i > 0 and line[i-1] in " \t":
1198 i = i-1
1199 line = line[:i]
1200 more = self.interp.runsource(line)
David Scherer7aced172000-08-15 01:13:23 +00001201
David Scherer7aced172000-08-15 01:13:23 +00001202 def open_stack_viewer(self, event=None):
Chui Tey5d2af632002-05-26 13:36:41 +00001203 if self.interp.rpcclt:
1204 return self.interp.remote_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +00001205 try:
1206 sys.last_traceback
1207 except:
1208 tkMessageBox.showerror("No stack trace",
1209 "There is no stack trace yet.\n"
1210 "(sys.last_traceback is not defined)",
1211 master=self.text)
1212 return
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +00001213 from idlelib.StackViewer import StackBrowser
David Scherer7aced172000-08-15 01:13:23 +00001214 sv = StackBrowser(self.root, self.flist)
1215
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001216 def view_restart_mark(self, event=None):
1217 self.text.see("iomark")
1218 self.text.see("restart")
1219
1220 def restart_shell(self, event=None):
Terry Jan Reedyda4c4672012-01-31 02:26:32 -05001221 "Callback for Run/Restart Shell Cntl-F6"
1222 self.interp.restart_subprocess(with_cwd=True)
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001223
David Scherer7aced172000-08-15 01:13:23 +00001224 def showprompt(self):
1225 self.resetoutput()
1226 try:
1227 s = str(sys.ps1)
1228 except:
1229 s = ""
1230 self.console.write(s)
1231 self.text.mark_set("insert", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001232 self.set_line_and_column()
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +00001233 self.io.reset_undo()
David Scherer7aced172000-08-15 01:13:23 +00001234
1235 def resetoutput(self):
1236 source = self.text.get("iomark", "end-1c")
1237 if self.history:
1238 self.history.history_store(source)
1239 if self.text.get("end-2c") != "\n":
1240 self.text.insert("end-1c", "\n")
1241 self.text.mark_set("iomark", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001242 self.set_line_and_column()
David Scherer7aced172000-08-15 01:13:23 +00001243
1244 def write(self, s, tags=()):
Andrew Svetlov05bab932012-03-14 13:22:12 -07001245 if isinstance(s, str) and len(s) and max(s) > '\uffff':
1246 # Tk doesn't support outputting non-BMP characters
1247 # Let's assume what printed string is not very long,
1248 # find first non-BMP character and construct informative
1249 # UnicodeEncodeError exception.
1250 for start, char in enumerate(s):
1251 if char > '\uffff':
1252 break
1253 raise UnicodeEncodeError("UCS-2", char, start, start+1,
1254 'Non-BMP character not supported in Tk')
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001255 try:
1256 self.text.mark_gravity("iomark", "right")
Martin v. Löwis30d5e6c2012-07-25 11:32:26 +02001257 count = OutputWindow.write(self, s, tags, "iomark")
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001258 self.text.mark_gravity("iomark", "left")
1259 except:
Kurt B. Kaisercbbe98f2007-08-12 01:52:35 +00001260 raise ###pass # ### 11Aug07 KBK if we are expecting exceptions
1261 # let's find out what they are and be specific.
David Scherer7aced172000-08-15 01:13:23 +00001262 if self.canceled:
1263 self.canceled = 0
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001264 if not use_subprocess:
1265 raise KeyboardInterrupt
Martin v. Löwis30d5e6c2012-07-25 11:32:26 +02001266 return count
David Scherer7aced172000-08-15 01:13:23 +00001267
Andrew Svetlovd1837672012-11-01 22:41:19 +02001268 def rmenu_check_cut(self):
1269 try:
1270 if self.text.compare('sel.first', '<', 'iomark'):
1271 return 'disabled'
1272 except TclError: # no selection, so the index 'sel.first' doesn't exist
1273 return 'disabled'
1274 return super().rmenu_check_cut()
1275
1276 def rmenu_check_paste(self):
1277 if self.text.compare('insert','<','iomark'):
1278 return 'disabled'
1279 return super().rmenu_check_paste()
1280
Kurt B. Kaiserdcba6622004-12-21 22:10:32 +00001281class PseudoFile(object):
David Scherer7aced172000-08-15 01:13:23 +00001282
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001283 def __init__(self, shell, tags, encoding=None):
David Scherer7aced172000-08-15 01:13:23 +00001284 self.shell = shell
1285 self.tags = tags
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001286 self.encoding = encoding
David Scherer7aced172000-08-15 01:13:23 +00001287
1288 def write(self, s):
Martin v. Löwis9ae3f7a2012-07-09 20:46:11 +02001289 if not isinstance(s, str):
1290 raise TypeError('must be str, not ' + type(s).__name__)
Martin v. Löwis30d5e6c2012-07-25 11:32:26 +02001291 return self.shell.write(s, self.tags)
David Scherer7aced172000-08-15 01:13:23 +00001292
Kurt B. Kaiser66aaf742007-08-09 18:00:23 +00001293 def writelines(self, lines):
1294 for line in lines:
1295 self.write(line)
David Scherer7aced172000-08-15 01:13:23 +00001296
1297 def flush(self):
1298 pass
1299
1300 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001301 return True
David Scherer7aced172000-08-15 01:13:23 +00001302
Martin v. Löwisc882b7c2012-07-25 10:47:20 +02001303class PseudoInputFile(object):
1304 def __init__(self, shell):
1305 self.readline = shell.readline
1306 self.isatty = shell.isatty
1307
1308 def write(self, s):
1309 raise io.UnsupportedOperation("not writable")
1310 writelines = write
1311
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001312
David Scherer7aced172000-08-15 01:13:23 +00001313usage_msg = """\
David Scherer7aced172000-08-15 01:13:23 +00001314
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001315USAGE: idle [-deins] [-t title] [file]*
1316 idle [-dns] [-t title] (-c cmd | -r file) [arg]*
1317 idle [-dns] [-t title] - [arg]*
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001318
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001319 -h print this help message and exit
Andrew Svetlov9b1e59a2012-10-05 22:12:44 +03001320 -n run IDLE without a subprocess (DEPRECATED,
1321 see Help/IDLE Help for details)
David Scherer7aced172000-08-15 01:13:23 +00001322
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001323The following options will override the IDLE 'settings' configuration:
Kurt B. Kaiser96d88422001-07-17 04:59:01 +00001324
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001325 -e open an edit window
1326 -i open a shell window
1327
1328The following options imply -i and will open a shell:
1329
1330 -c cmd run the command in a shell, or
1331 -r file run script from file
1332
1333 -d enable the debugger
1334 -s run $IDLESTARTUP or $PYTHONSTARTUP before anything else
1335 -t title set title of shell window
1336
1337A default edit window will be bypassed when -c, -r, or - are used.
1338
1339[arg]* are passed to the command (-c) or script (-r) in sys.argv[1:].
1340
1341Examples:
1342
1343idle
1344 Open an edit window or shell depending on IDLE's configuration.
1345
1346idle foo.py foobar.py
1347 Edit the files, also open a shell if configured to start with shell.
1348
1349idle -est "Baz" foo.py
1350 Run $IDLESTARTUP or $PYTHONSTARTUP, edit foo.py, and open a shell
1351 window with the title "Baz".
1352
Neal Norwitz752abd02008-05-13 04:55:24 +00001353idle -c "import sys; print(sys.argv)" "foo"
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001354 Open a shell window and run the command, passing "-c" in sys.argv[0]
1355 and "foo" in sys.argv[1].
1356
1357idle -d -s -r foo.py "Hello World"
1358 Open a shell window, run a startup script, enable the debugger, and
1359 run foo.py, passing "foo.py" in sys.argv[0] and "Hello World" in
1360 sys.argv[1].
1361
Neal Norwitz752abd02008-05-13 04:55:24 +00001362echo "import sys; print(sys.argv)" | idle - "foobar"
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001363 Open a shell window, run the script piped in, passing '' in sys.argv[0]
1364 and "foobar" in sys.argv[1].
David Scherer7aced172000-08-15 01:13:23 +00001365"""
1366
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001367def main():
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001368 global flist, root, use_subprocess
David Scherer7aced172000-08-15 01:13:23 +00001369
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001370 use_subprocess = True
Kurt B. Kaisere866c812009-04-04 21:07:39 +00001371 enable_shell = True
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001372 enable_edit = False
1373 debug = False
1374 cmd = None
1375 script = None
1376 startup = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001377 try:
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001378 opts, args = getopt.getopt(sys.argv[1:], "c:deihnr:st:")
Guido van Rossumb940e112007-01-10 16:19:56 +00001379 except getopt.error as msg:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001380 sys.stderr.write("Error: %s\n" % str(msg))
1381 sys.stderr.write(usage_msg)
1382 sys.exit(2)
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001383 for o, a in opts:
1384 if o == '-c':
1385 cmd = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001386 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001387 if o == '-d':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001388 debug = True
1389 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001390 if o == '-e':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001391 enable_edit = True
Kurt B. Kaisere866c812009-04-04 21:07:39 +00001392 enable_shell = False
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001393 if o == '-h':
1394 sys.stdout.write(usage_msg)
1395 sys.exit()
1396 if o == '-i':
1397 enable_shell = True
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001398 if o == '-n':
Andrew Svetlov9b1e59a2012-10-05 22:12:44 +03001399 print(" Warning: running IDLE without a subprocess is deprecated.",
1400 file=sys.stderr)
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001401 use_subprocess = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001402 if o == '-r':
1403 script = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001404 if os.path.isfile(script):
1405 pass
1406 else:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001407 print("No script file: ", script)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001408 sys.exit()
1409 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001410 if o == '-s':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001411 startup = True
1412 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001413 if o == '-t':
1414 PyShell.shell_title = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001415 enable_shell = True
1416 if args and args[0] == '-':
1417 cmd = sys.stdin.read()
1418 enable_shell = True
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001419 # process sys.argv and sys.path:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001420 for i in range(len(sys.path)):
1421 sys.path[i] = os.path.abspath(sys.path[i])
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001422 if args and args[0] == '-':
1423 sys.argv = [''] + args[1:]
1424 elif cmd:
1425 sys.argv = ['-c'] + args
1426 elif script:
1427 sys.argv = [script] + args
1428 elif args:
1429 enable_edit = True
1430 pathx = []
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001431 for filename in args:
1432 pathx.append(os.path.dirname(filename))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001433 for dir in pathx:
1434 dir = os.path.abspath(dir)
1435 if not dir in sys.path:
1436 sys.path.insert(0, dir)
Kurt B. Kaiserff002b92002-12-21 21:39:11 +00001437 else:
Neal Norwitzd082b6e2007-08-26 23:37:53 +00001438 dir = os.getcwd()
1439 if dir not in sys.path:
Kurt B. Kaiserff002b92002-12-21 21:39:11 +00001440 sys.path.insert(0, dir)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001441 # check the IDLE settings configuration (but command line overrides)
1442 edit_start = idleConf.GetOption('main', 'General',
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001443 'editor-on-startup', type='bool')
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001444 enable_edit = enable_edit or edit_start
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001445 # start editor and/or shell windows:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001446 root = Tk(className="Idle")
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001447
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001448 fixwordbreaks(root)
1449 root.withdraw()
1450 flist = PyShellFileList(root)
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001451 macosxSupport.setupApp(root, flist)
1452
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001453 if enable_edit:
1454 if not (cmd or script):
Andrew Svetlov6b6e4372012-03-20 23:03:26 +02001455 for filename in args[:]:
1456 if flist.open(filename) is None:
1457 # filename is a directory actually, disconsider it
1458 args.remove(filename)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001459 if not args:
1460 flist.new()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001461 if enable_shell:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001462 shell = flist.open_shell()
1463 if not shell:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001464 return # couldn't open shell
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001465
1466 if macosxSupport.runningAsOSXApp() and flist.dict:
1467 # On OSX: when the user has double-clicked on a file that causes
1468 # IDLE to be launched the shell window will open just in front of
1469 # the file she wants to see. Lower the interpreter window when
1470 # there are open files.
1471 shell.top.lower()
1472
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001473 shell = flist.pyshell
1474 # handle remaining options:
1475 if debug:
1476 shell.open_debugger()
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001477 if startup:
1478 filename = os.environ.get("IDLESTARTUP") or \
1479 os.environ.get("PYTHONSTARTUP")
1480 if filename and os.path.isfile(filename):
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001481 shell.interp.execfile(filename)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001482 if shell and cmd or script:
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001483 shell.interp.runcommand("""if 1:
1484 import sys as _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001485 _sys.argv = %r
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001486 del _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001487 \n""" % (sys.argv,))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001488 if cmd:
1489 shell.interp.execsource(cmd)
1490 elif script:
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001491 shell.interp.prepend_syspath(script)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001492 shell.interp.execfile(script)
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001493
Ned Deily4ce92b22011-01-15 04:37:12 +00001494 # Check for problematic OS X Tk versions and print a warning message
1495 # in the IDLE shell window; this is less intrusive than always opening
1496 # a separate window.
1497 tkversionwarning = macosxSupport.tkVersionWarning(root)
1498 if tkversionwarning:
1499 shell.interp.runcommand(''.join(("print('", tkversionwarning, "')")))
1500
Terry Jan Reedycd6b8c62012-05-26 20:23:45 -04001501 while flist.inversedict: # keep IDLE running while files are open.
1502 root.mainloop()
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001503 root.destroy()
1504
David Scherer7aced172000-08-15 01:13:23 +00001505if __name__ == "__main__":
Kurt B. Kaiser9e8b8282003-06-15 17:38:45 +00001506 sys.modules['PyShell'] = sys.modules['__main__']
David Scherer7aced172000-08-15 01:13:23 +00001507 main()