blob: 9ccb31cb840845f95eacb4d0bb9a10a732341cb9 [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))
Andrew Svetlovf7a17b42012-12-25 16:47:37 +020061 except OSError:
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000062 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()
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200214 except OSError:
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')
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200225 except OSError as err:
Ned Deilyf505b742011-12-14 14:58:24 -0800226 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
Andrew Svetlov0832af62012-12-18 23:10:48 +0200396 except OSError 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
Serhiy Storchaka39e70a42013-01-25 15:30:58 +0200420 self.rpcclt.register("console", self.tkconsole)
421 self.rpcclt.register("stdin", self.tkconsole.stdin)
Kurt B. Kaiser969de452002-06-12 03:28:57 +0000422 self.rpcclt.register("stdout", self.tkconsole.stdout)
423 self.rpcclt.register("stderr", self.tkconsole.stderr)
Chui Tey5d2af632002-05-26 13:36:41 +0000424 self.rpcclt.register("flist", self.tkconsole.flist)
Kurt B. Kaiser8cd0def2003-01-31 05:06:43 +0000425 self.rpcclt.register("linecache", linecache)
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000426 self.rpcclt.register("interp", self)
Terry Jan Reedyda4c4672012-01-31 02:26:32 -0500427 self.transfer_path(with_cwd=True)
Chui Tey5d2af632002-05-26 13:36:41 +0000428 self.poll_subprocess()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000429 return self.rpcclt
Chui Tey5d2af632002-05-26 13:36:41 +0000430
Terry Jan Reedyda4c4672012-01-31 02:26:32 -0500431 def restart_subprocess(self, with_cwd=False):
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000432 if self.restarting:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000433 return self.rpcclt
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000434 self.restarting = True
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000435 # close only the subprocess debugger
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000436 debug = self.getdebugger()
437 if debug:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000438 try:
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000439 # Only close subprocess debugger, don't unregister gui_adap!
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000440 RemoteDebugger.close_subprocess_debugger(self.rpcclt)
441 except:
442 pass
443 # Kill subprocess, spawn a new one, accept connection.
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000444 self.rpcclt.close()
Ned Deilye5cad232011-08-02 18:47:13 -0700445 self.terminate_subprocess()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000446 console = self.tkconsole
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000447 was_executing = console.executing
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000448 console.executing = False
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000449 self.spawn_subprocess()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000450 try:
451 self.rpcclt.accept()
Guido van Rossumb940e112007-01-10 16:19:56 +0000452 except socket.timeout as err:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000453 self.display_no_subprocess_error()
454 return None
Terry Jan Reedyda4c4672012-01-31 02:26:32 -0500455 self.transfer_path(with_cwd=with_cwd)
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000456 # annotate restart in shell window and mark it
Kurt B. Kaiser4cc5ef52003-01-22 00:23:23 +0000457 console.text.delete("iomark", "end-1c")
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000458 if was_executing:
459 console.write('\n')
460 console.showprompt()
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000461 halfbar = ((int(console.width) - 16) // 2) * '='
462 console.write(halfbar + ' RESTART ' + halfbar)
463 console.text.mark_set("restart", "end-1c")
464 console.text.mark_gravity("restart", "left")
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000465 console.showprompt()
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000466 # restart subprocess debugger
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000467 if debug:
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000468 # Restarted debugger connects to current instance of debug GUI
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000469 gui = RemoteDebugger.restart_subprocess_debugger(self.rpcclt)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000470 # reload remote debugger breakpoints for all PyShellEditWindows
471 debug.load_breakpoints()
Ned Deily7aff4512011-10-30 20:01:35 -0700472 self.compile.compiler.flags = self.original_compiler_flags
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000473 self.restarting = False
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000474 return self.rpcclt
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000475
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000476 def __request_interrupt(self):
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000477 self.rpcclt.remotecall("exec", "interrupt_the_server", (), {})
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000478
479 def interrupt_subprocess(self):
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000480 threading.Thread(target=self.__request_interrupt).start()
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000481
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000482 def kill_subprocess(self):
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000483 try:
Ned Deily55f87572011-11-05 22:36:44 -0700484 self.rpcclt.listening_sock.close()
485 except AttributeError: # no socket
486 pass
487 try:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000488 self.rpcclt.close()
489 except AttributeError: # no socket
490 pass
Ned Deilye5cad232011-08-02 18:47:13 -0700491 self.terminate_subprocess()
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000492 self.tkconsole.executing = False
493 self.rpcclt = None
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000494
Ned Deilye5cad232011-08-02 18:47:13 -0700495 def terminate_subprocess(self):
496 "Make sure subprocess is terminated"
497 try:
498 self.rpcsubproc.kill()
499 except OSError:
500 # process already terminated
501 return
502 else:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000503 try:
Ned Deilye5cad232011-08-02 18:47:13 -0700504 self.rpcsubproc.wait()
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000505 except OSError:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000506 return
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000507
Terry Jan Reedyda4c4672012-01-31 02:26:32 -0500508 def transfer_path(self, with_cwd=False):
509 if with_cwd: # Issue 13506
510 path = [''] # include Current Working Directory
511 path.extend(sys.path)
512 else:
513 path = sys.path
Terry Jan Reedy4d82ade2012-01-31 02:57:29 -0500514
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000515 self.runcommand("""if 1:
516 import sys as _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +0000517 _sys.path = %r
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000518 del _sys
Terry Jan Reedyda4c4672012-01-31 02:26:32 -0500519 \n""" % (path,))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000520
Chui Tey5d2af632002-05-26 13:36:41 +0000521 active_seq = None
522
523 def poll_subprocess(self):
524 clt = self.rpcclt
525 if clt is None:
526 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000527 try:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000528 response = clt.pollresponse(self.active_seq, wait=0.05)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200529 except (EOFError, OSError, KeyboardInterrupt):
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000530 # lost connection or subprocess terminated itself, restart
531 # [the KBI is from rpc.SocketIO.handle_EOF()]
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000532 if self.tkconsole.closing:
533 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000534 response = None
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000535 self.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000536 if response:
537 self.tkconsole.resetoutput()
538 self.active_seq = None
539 how, what = response
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000540 console = self.tkconsole.console
Chui Tey5d2af632002-05-26 13:36:41 +0000541 if how == "OK":
542 if what is not None:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000543 print(repr(what), file=console)
Chui Tey5d2af632002-05-26 13:36:41 +0000544 elif how == "EXCEPTION":
Chui Tey5d2af632002-05-26 13:36:41 +0000545 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
546 self.remote_stack_viewer()
547 elif how == "ERROR":
Kurt B. Kaiser0930c432002-12-06 21:45:24 +0000548 errmsg = "PyShell.ModifiedInterpreter: Subprocess ERROR:\n"
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000549 print(errmsg, what, file=sys.__stderr__)
550 print(errmsg, what, file=console)
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000551 # we received a response to the currently active seq number:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000552 try:
553 self.tkconsole.endexecuting()
554 except AttributeError: # shell may have closed
555 pass
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000556 # Reschedule myself
557 if not self.tkconsole.closing:
558 self.tkconsole.text.after(self.tkconsole.pollinterval,
559 self.poll_subprocess)
Chui Tey5d2af632002-05-26 13:36:41 +0000560
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000561 debugger = None
562
563 def setdebugger(self, debugger):
564 self.debugger = debugger
565
566 def getdebugger(self):
567 return self.debugger
568
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000569 def open_remote_stack_viewer(self):
570 """Initiate the remote stack viewer from a separate thread.
571
572 This method is called from the subprocess, and by returning from this
573 method we allow the subprocess to unblock. After a bit the shell
574 requests the subprocess to open the remote stack viewer which returns a
Ezio Melotti60861182010-07-23 16:48:22 +0000575 static object looking at the last exception. It is queried through
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000576 the RPC mechanism.
577
578 """
579 self.tkconsole.text.after(300, self.remote_stack_viewer)
580 return
581
Chui Tey5d2af632002-05-26 13:36:41 +0000582 def remote_stack_viewer(self):
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000583 from idlelib import RemoteObjectBrowser
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000584 oid = self.rpcclt.remotequeue("exec", "stackviewer", ("flist",), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000585 if oid is None:
586 self.tkconsole.root.bell()
587 return
588 item = RemoteObjectBrowser.StubObjectTreeItem(self.rpcclt, oid)
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000589 from idlelib.TreeWidget import ScrolledCanvas, TreeNode
Chui Tey5d2af632002-05-26 13:36:41 +0000590 top = Toplevel(self.tkconsole.root)
Kurt B. Kaiser73360a32004-03-08 18:15:31 +0000591 theme = idleConf.GetOption('main','Theme','name')
592 background = idleConf.GetHighlight(theme, 'normal')['background']
593 sc = ScrolledCanvas(top, bg=background, highlightthickness=0)
Chui Tey5d2af632002-05-26 13:36:41 +0000594 sc.frame.pack(expand=1, fill="both")
595 node = TreeNode(sc.canvas, None, item)
596 node.expand()
597 # XXX Should GC the remote tree when closing the window
598
David Scherer7aced172000-08-15 01:13:23 +0000599 gid = 0
600
601 def execsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000602 "Like runsource() but assumes complete exec source"
David Scherer7aced172000-08-15 01:13:23 +0000603 filename = self.stuffsource(source)
604 self.execfile(filename, source)
605
606 def execfile(self, filename, source=None):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000607 "Execute an existing file"
David Scherer7aced172000-08-15 01:13:23 +0000608 if source is None:
Victor Stinner979482a2011-09-02 01:00:40 +0200609 with tokenize.open(filename) as fp:
Victor Stinner85c67722011-09-02 00:57:04 +0200610 source = fp.read()
David Scherer7aced172000-08-15 01:13:23 +0000611 try:
612 code = compile(source, filename, "exec")
613 except (OverflowError, SyntaxError):
614 self.tkconsole.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000615 tkerr = self.tkconsole.stderr
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000616 print('*** Error in script or command!\n', file=tkerr)
617 print('Traceback (most recent call last):', file=tkerr)
David Scherer7aced172000-08-15 01:13:23 +0000618 InteractiveInterpreter.showsyntaxerror(self, filename)
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000619 self.tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000620 else:
621 self.runcode(code)
622
623 def runsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000624 "Extend base class method: Stuff the source in the line cache first"
David Scherer7aced172000-08-15 01:13:23 +0000625 filename = self.stuffsource(source)
626 self.more = 0
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000627 self.save_warnings_filters = warnings.filters[:]
628 warnings.filterwarnings(action="error", category=SyntaxWarning)
Martin v. Löwis98ff8982007-08-13 06:03:15 +0000629 # at the moment, InteractiveInterpreter expects str
630 assert isinstance(source, str)
631 #if isinstance(source, str):
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000632 # from idlelib import IOBinding
Martin v. Löwis98ff8982007-08-13 06:03:15 +0000633 # try:
634 # source = source.encode(IOBinding.encoding)
635 # except UnicodeError:
636 # self.tkconsole.resetoutput()
637 # self.write("Unsupported characters in input\n")
638 # return
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000639 try:
Kurt B. Kaiser935ea9a2005-05-10 03:44:24 +0000640 # InteractiveInterpreter.runsource() calls its runcode() method,
641 # which is overridden (see below)
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000642 return InteractiveInterpreter.runsource(self, source, filename)
643 finally:
644 if self.save_warnings_filters is not None:
645 warnings.filters[:] = self.save_warnings_filters
646 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000647
648 def stuffsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000649 "Stuff source in the filename cache"
David Scherer7aced172000-08-15 01:13:23 +0000650 filename = "<pyshell#%d>" % self.gid
651 self.gid = self.gid + 1
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000652 lines = source.split("\n")
David Scherer7aced172000-08-15 01:13:23 +0000653 linecache.cache[filename] = len(source)+1, 0, lines, filename
654 return filename
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000655
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000656 def prepend_syspath(self, filename):
657 "Prepend sys.path with file's directory if not already included"
658 self.runcommand("""if 1:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000659 _filename = %r
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000660 import sys as _sys
661 from os.path import dirname as _dirname
662 _dir = _dirname(_filename)
663 if not _dir in _sys.path:
664 _sys.path.insert(0, _dir)
665 del _filename, _sys, _dirname, _dir
Walter Dörwald70a6b492004-02-12 17:35:32 +0000666 \n""" % (filename,))
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000667
David Scherer7aced172000-08-15 01:13:23 +0000668 def showsyntaxerror(self, filename=None):
Guido van Rossum33d26892007-08-05 15:29:28 +0000669 """Override Interactive Interpreter method: Use Colorizing
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000670
671 Color the offending position instead of printing it and pointing at it
672 with a caret.
673
674 """
Guido van Rossum33d26892007-08-05 15:29:28 +0000675 tkconsole = self.tkconsole
676 text = tkconsole.text
677 text.tag_remove("ERROR", "1.0", "end")
David Scherer7aced172000-08-15 01:13:23 +0000678 type, value, tb = sys.exc_info()
Ned Deily79746422011-09-14 14:49:14 -0700679 msg = getattr(value, 'msg', '') or value or "<no detail available>"
680 lineno = getattr(value, 'lineno', '') or 1
681 offset = getattr(value, 'offset', '') or 0
Guido van Rossum33d26892007-08-05 15:29:28 +0000682 if offset == 0:
683 lineno += 1 #mark end of offending line
684 if lineno == 1:
685 pos = "iomark + %d chars" % (offset-1)
David Scherer7aced172000-08-15 01:13:23 +0000686 else:
Guido van Rossum33d26892007-08-05 15:29:28 +0000687 pos = "iomark linestart + %d lines + %d chars" % \
688 (lineno-1, offset-1)
689 tkconsole.colorize_syntax_error(text, pos)
690 tkconsole.resetoutput()
691 self.write("SyntaxError: %s\n" % msg)
692 tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000693
694 def showtraceback(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000695 "Extend base class method to reset output properly"
David Scherer7aced172000-08-15 01:13:23 +0000696 self.tkconsole.resetoutput()
697 self.checklinecache()
698 InteractiveInterpreter.showtraceback(self)
Chui Tey5d2af632002-05-26 13:36:41 +0000699 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
700 self.tkconsole.open_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +0000701
702 def checklinecache(self):
703 c = linecache.cache
Guido van Rossum36e0a922007-07-20 04:05:57 +0000704 for key in list(c.keys()):
David Scherer7aced172000-08-15 01:13:23 +0000705 if key[:1] + key[-1:] != "<>":
706 del c[key]
707
Chui Tey5d2af632002-05-26 13:36:41 +0000708 def runcommand(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000709 "Run the code without invoking the debugger"
Chui Tey5d2af632002-05-26 13:36:41 +0000710 # The code better not raise an exception!
711 if self.tkconsole.executing:
Neal Norwitzf4c4f112002-11-30 18:49:10 +0000712 self.display_executing_dialog()
Chui Tey5d2af632002-05-26 13:36:41 +0000713 return 0
714 if self.rpcclt:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000715 self.rpcclt.remotequeue("exec", "runcode", (code,), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000716 else:
Georg Brandl7cae87c2006-09-06 06:51:57 +0000717 exec(code, self.locals)
Chui Tey5d2af632002-05-26 13:36:41 +0000718 return 1
719
David Scherer7aced172000-08-15 01:13:23 +0000720 def runcode(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000721 "Override base class method"
Chui Tey5d2af632002-05-26 13:36:41 +0000722 if self.tkconsole.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000723 self.interp.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000724 self.checklinecache()
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000725 if self.save_warnings_filters is not None:
726 warnings.filters[:] = self.save_warnings_filters
727 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000728 debugger = self.debugger
729 try:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000730 self.tkconsole.beginexecuting()
Thomas Wouterscf297e42007-02-23 15:07:44 +0000731 if not debugger and self.rpcclt is not None:
732 self.active_seq = self.rpcclt.asyncqueue("exec", "runcode",
733 (code,), {})
734 elif debugger:
735 debugger.run(code, self.locals)
736 else:
737 exec(code, self.locals)
738 except SystemExit:
739 if not self.tkconsole.closing:
740 if tkMessageBox.askyesno(
741 "Exit?",
742 "Do you want to exit altogether?",
743 default="yes",
744 master=self.tkconsole.text):
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000745 raise
Thomas Wouterscf297e42007-02-23 15:07:44 +0000746 else:
Guido van Rossum5dc0d972007-02-25 22:37:36 +0000747 self.showtraceback()
Thomas Wouterscf297e42007-02-23 15:07:44 +0000748 else:
749 raise
750 except:
751 if use_subprocess:
752 print("IDLE internal error in runcode()",
753 file=self.tkconsole.stderr)
David Scherer7aced172000-08-15 01:13:23 +0000754 self.showtraceback()
Thomas Wouterscf297e42007-02-23 15:07:44 +0000755 self.tkconsole.endexecuting()
756 else:
757 if self.tkconsole.canceled:
758 self.tkconsole.canceled = False
759 print("KeyboardInterrupt", file=self.tkconsole.stderr)
760 else:
761 self.showtraceback()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000762 finally:
763 if not use_subprocess:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000764 try:
765 self.tkconsole.endexecuting()
766 except AttributeError: # shell may have closed
767 pass
David Scherer7aced172000-08-15 01:13:23 +0000768
769 def write(self, s):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000770 "Override base class method"
Martin v. Löwis30d5e6c2012-07-25 11:32:26 +0200771 return self.tkconsole.stderr.write(s)
David Scherer7aced172000-08-15 01:13:23 +0000772
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000773 def display_port_binding_error(self):
774 tkMessageBox.showerror(
775 "Port Binding Error",
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000776 "IDLE can't bind to a TCP/IP port, which is necessary to "
777 "communicate with its Python execution server. This might be "
778 "because no networking is installed on this computer. "
779 "Run IDLE with the -n command line switch to start without a "
780 "subprocess and refer to Help/IDLE Help 'Running without a "
781 "subprocess' for further details.",
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000782 master=self.tkconsole.text)
783
784 def display_no_subprocess_error(self):
785 tkMessageBox.showerror(
786 "Subprocess Startup Error",
787 "IDLE's subprocess didn't make connection. Either IDLE can't "
788 "start a subprocess or personal firewall software is blocking "
789 "the connection.",
790 master=self.tkconsole.text)
791
792 def display_executing_dialog(self):
793 tkMessageBox.showerror(
794 "Already executing",
795 "The Python Shell window is already executing a command; "
796 "please wait until it is finished.",
797 master=self.tkconsole.text)
798
799
David Scherer7aced172000-08-15 01:13:23 +0000800class PyShell(OutputWindow):
801
802 shell_title = "Python Shell"
803
804 # Override classes
805 ColorDelegator = ModifiedColorDelegator
806 UndoDelegator = ModifiedUndoDelegator
807
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000808 # Override menus
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000809 menu_specs = [
810 ("file", "_File"),
811 ("edit", "_Edit"),
Kurt B. Kaiser4cc5ef52003-01-22 00:23:23 +0000812 ("debug", "_Debug"),
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000813 ("options", "_Options"),
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000814 ("windows", "_Windows"),
815 ("help", "_Help"),
816 ]
David Scherer7aced172000-08-15 01:13:23 +0000817
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000818 if macosxSupport.runningAsOSXApp():
819 del menu_specs[-3]
820 menu_specs[-2] = ("windows", "_Window")
821
822
David Scherer7aced172000-08-15 01:13:23 +0000823 # New classes
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000824 from idlelib.IdleHistory import History
David Scherer7aced172000-08-15 01:13:23 +0000825
826 def __init__(self, flist=None):
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000827 if use_subprocess:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000828 ms = self.menu_specs
829 if ms[2][0] != "shell":
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000830 ms.insert(2, ("shell", "She_ll"))
David Scherer7aced172000-08-15 01:13:23 +0000831 self.interp = ModifiedInterpreter(self)
832 if flist is None:
833 root = Tk()
834 fixwordbreaks(root)
835 root.withdraw()
836 flist = PyShellFileList(root)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000837 #
David Scherer7aced172000-08-15 01:13:23 +0000838 OutputWindow.__init__(self, flist, None, None)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000839 #
Kurt B. Kaiser6af44982005-01-19 00:22:59 +0000840## self.config(usetabs=1, indentwidth=8, context_use_ps1=1)
841 self.usetabs = True
842 # indentwidth must be 8 when using tabs. See note in EditorWindow:
843 self.indentwidth = 8
844 self.context_use_ps1 = True
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000845 #
David Scherer7aced172000-08-15 01:13:23 +0000846 text = self.text
847 text.configure(wrap="char")
848 text.bind("<<newline-and-indent>>", self.enter_callback)
849 text.bind("<<plain-newline-and-indent>>", self.linefeed_callback)
850 text.bind("<<interrupt-execution>>", self.cancel_callback)
David Scherer7aced172000-08-15 01:13:23 +0000851 text.bind("<<end-of-file>>", self.eof_callback)
852 text.bind("<<open-stack-viewer>>", self.open_stack_viewer)
Kurt B. Kaiser57bfe5d2003-05-10 00:09:52 +0000853 text.bind("<<toggle-debugger>>", self.toggle_debugger)
David Scherer7aced172000-08-15 01:13:23 +0000854 text.bind("<<toggle-jit-stack-viewer>>", self.toggle_jit_stack_viewer)
Kurt B. Kaiser8a78cad2007-12-13 03:38:16 +0000855 self.color = color = self.ColorDelegator()
856 self.per.insertfilter(color)
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000857 if use_subprocess:
858 text.bind("<<view-restart>>", self.view_restart_mark)
859 text.bind("<<restart-shell>>", self.restart_shell)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000860 #
David Scherer7aced172000-08-15 01:13:23 +0000861 self.save_stdout = sys.stdout
862 self.save_stderr = sys.stderr
863 self.save_stdin = sys.stdin
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000864 from idlelib import IOBinding
Serhiy Storchaka39e70a42013-01-25 15:30:58 +0200865 self.stdin = PseudoInputFile(self, "stdin", IOBinding.encoding)
866 self.stdout = PseudoOutputFile(self, "stdout", IOBinding.encoding)
867 self.stderr = PseudoOutputFile(self, "stderr", IOBinding.encoding)
868 self.console = PseudoOutputFile(self, "console", IOBinding.encoding)
Chui Tey5d2af632002-05-26 13:36:41 +0000869 if not use_subprocess:
870 sys.stdout = self.stdout
Kurt B. Kaiser7cec2522007-08-31 04:15:13 +0000871 sys.stderr = self.stderr
Martin v. Löwisc882b7c2012-07-25 10:47:20 +0200872 sys.stdin = self.stdin
Kurt B. Kaiserf609a342007-12-28 03:57:56 +0000873 try:
874 # page help() text to shell.
875 import pydoc # import must be done here to capture i/o rebinding.
876 # XXX KBK 27Dec07 use a textView someday, but must work w/o subproc
877 pydoc.pager = pydoc.plainpager
878 except:
879 sys.stderr = sys.__stderr__
880 raise
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000881 #
David Scherer7aced172000-08-15 01:13:23 +0000882 self.history = self.History(self.text)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000883 #
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000884 self.pollinterval = 50 # millisec
Chui Tey5d2af632002-05-26 13:36:41 +0000885
Kurt B. Kaiser4d5bc602004-06-06 01:29:22 +0000886 def get_standard_extension_names(self):
887 return idleConf.GetExtensions(shell_only=True)
888
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000889 reading = False
890 executing = False
891 canceled = False
892 endoffile = False
893 closing = False
David Scherer7aced172000-08-15 01:13:23 +0000894
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +0000895 def set_warning_stream(self, stream):
Skip Montanarod9161422004-07-06 21:53:27 +0000896 global warning_stream
897 warning_stream = stream
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +0000898
899 def get_warning_stream(self):
900 return warning_stream
901
David Scherer7aced172000-08-15 01:13:23 +0000902 def toggle_debugger(self, event=None):
903 if self.executing:
904 tkMessageBox.showerror("Don't debug now",
905 "You can only toggle the debugger when idle",
906 master=self.text)
907 self.set_debugger_indicator()
908 return "break"
909 else:
910 db = self.interp.getdebugger()
911 if db:
912 self.close_debugger()
913 else:
914 self.open_debugger()
915
916 def set_debugger_indicator(self):
917 db = self.interp.getdebugger()
918 self.setvar("<<toggle-debugger>>", not not db)
919
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000920 def toggle_jit_stack_viewer(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +0000921 pass # All we need is the variable
922
923 def close_debugger(self):
924 db = self.interp.getdebugger()
925 if db:
926 self.interp.setdebugger(None)
927 db.close()
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000928 if self.interp.rpcclt:
929 RemoteDebugger.close_remote_debugger(self.interp.rpcclt)
David Scherer7aced172000-08-15 01:13:23 +0000930 self.resetoutput()
931 self.console.write("[DEBUG OFF]\n")
932 sys.ps1 = ">>> "
933 self.showprompt()
934 self.set_debugger_indicator()
935
936 def open_debugger(self):
Chui Tey5d2af632002-05-26 13:36:41 +0000937 if self.interp.rpcclt:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000938 dbg_gui = RemoteDebugger.start_remote_debugger(self.interp.rpcclt,
939 self)
940 else:
941 dbg_gui = Debugger.Debugger(self)
942 self.interp.setdebugger(dbg_gui)
943 dbg_gui.load_breakpoints()
Chui Tey5d2af632002-05-26 13:36:41 +0000944 sys.ps1 = "[DEBUG ON]\n>>> "
945 self.showprompt()
946 self.set_debugger_indicator()
947
David Scherer7aced172000-08-15 01:13:23 +0000948 def beginexecuting(self):
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000949 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +0000950 self.resetoutput()
951 self.executing = 1
David Scherer7aced172000-08-15 01:13:23 +0000952
953 def endexecuting(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000954 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +0000955 self.executing = 0
956 self.canceled = 0
Chui Tey5d2af632002-05-26 13:36:41 +0000957 self.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000958
959 def close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000960 "Extend EditorWindow.close()"
David Scherer7aced172000-08-15 01:13:23 +0000961 if self.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000962 response = tkMessageBox.askokcancel(
David Scherer7aced172000-08-15 01:13:23 +0000963 "Kill?",
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000964 "The program is still running!\n Do you want to kill it?",
David Scherer7aced172000-08-15 01:13:23 +0000965 default="ok",
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000966 parent=self.text)
Benjamin Peterson2a691a82008-03-31 01:51:45 +0000967 if response is False:
David Scherer7aced172000-08-15 01:13:23 +0000968 return "cancel"
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +0000969 if self.reading:
970 self.top.quit()
971 self.canceled = True
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000972 self.closing = True
973 # Wait for poll_subprocess() rescheduling to stop
974 self.text.after(2 * self.pollinterval, self.close2)
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000975
976 def close2(self):
977 return EditorWindow.close(self)
David Scherer7aced172000-08-15 01:13:23 +0000978
979 def _close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000980 "Extend EditorWindow._close(), shut down debugger and execution server"
David Scherer7aced172000-08-15 01:13:23 +0000981 self.close_debugger()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000982 if use_subprocess:
983 self.interp.kill_subprocess()
David Scherer7aced172000-08-15 01:13:23 +0000984 # Restore std streams
985 sys.stdout = self.save_stdout
986 sys.stderr = self.save_stderr
987 sys.stdin = self.save_stdin
988 # Break cycles
989 self.interp = None
990 self.console = None
David Scherer7aced172000-08-15 01:13:23 +0000991 self.flist.pyshell = None
992 self.history = None
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000993 EditorWindow._close(self)
David Scherer7aced172000-08-15 01:13:23 +0000994
995 def ispythonsource(self, filename):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000996 "Override EditorWindow method: never remove the colorizer"
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000997 return True
David Scherer7aced172000-08-15 01:13:23 +0000998
999 def short_title(self):
1000 return self.shell_title
1001
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +00001002 COPYRIGHT = \
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001003 'Type "copyright", "credits" or "license()" for more information.'
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +00001004
David Scherer7aced172000-08-15 01:13:23 +00001005 def begin(self):
Kurt B. Kaiser7378df72007-08-11 04:20:51 +00001006 self.text.mark_set("iomark", "insert")
David Scherer7aced172000-08-15 01:13:23 +00001007 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001008 if use_subprocess:
1009 nosub = ''
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001010 client = self.interp.start_subprocess()
1011 if not client:
1012 self.close()
Kurt B. Kaiser76637292004-01-21 22:10:01 +00001013 return False
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001014 else:
Andrew Svetlov9b1e59a2012-10-05 22:12:44 +03001015 nosub = ("==== No Subprocess ====\n\n" +
Andrew Svetlov64478ac2012-10-05 22:16:55 +03001016 "WARNING: Running IDLE without a Subprocess is deprecated\n" +
Andrew Svetlov9b1e59a2012-10-05 22:12:44 +03001017 "and will be removed in a later version. See Help/IDLE Help\n" +
1018 "for details.\n\n")
Andrew Svetlovcd49d532012-03-25 11:43:02 +03001019 sys.displayhook = rpc.displayhook
1020
Raymond Hettingera2a8e8b2009-01-27 00:28:36 +00001021 self.write("Python %s on %s\n%s\n%s" %
1022 (sys.version, sys.platform, self.COPYRIGHT, nosub))
David Scherer7aced172000-08-15 01:13:23 +00001023 self.showprompt()
Georg Brandl14fc4272008-05-17 18:39:55 +00001024 import tkinter
1025 tkinter._default_root = None # 03Jan04 KBK What's this?
Kurt B. Kaiser76637292004-01-21 22:10:01 +00001026 return True
David Scherer7aced172000-08-15 01:13:23 +00001027
1028 def readline(self):
1029 save = self.reading
1030 try:
1031 self.reading = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001032 self.top.mainloop() # nested mainloop()
David Scherer7aced172000-08-15 01:13:23 +00001033 finally:
1034 self.reading = save
1035 line = self.text.get("iomark", "end-1c")
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001036 if len(line) == 0: # may be EOF if we quit our mainloop with Ctrl-C
1037 line = "\n"
David Scherer7aced172000-08-15 01:13:23 +00001038 self.resetoutput()
1039 if self.canceled:
1040 self.canceled = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001041 if not use_subprocess:
1042 raise KeyboardInterrupt
David Scherer7aced172000-08-15 01:13:23 +00001043 if self.endoffile:
1044 self.endoffile = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001045 line = ""
David Scherer7aced172000-08-15 01:13:23 +00001046 return line
1047
1048 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001049 return True
David Scherer7aced172000-08-15 01:13:23 +00001050
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001051 def cancel_callback(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +00001052 try:
1053 if self.text.compare("sel.first", "!=", "sel.last"):
1054 return # Active selection -- always use default binding
1055 except:
1056 pass
1057 if not (self.executing or self.reading):
1058 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001059 self.interp.write("KeyboardInterrupt\n")
David Scherer7aced172000-08-15 01:13:23 +00001060 self.showprompt()
1061 return "break"
1062 self.endoffile = 0
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001063 self.canceled = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001064 if (self.executing and self.interp.rpcclt):
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +00001065 if self.interp.getdebugger():
1066 self.interp.restart_subprocess()
1067 else:
1068 self.interp.interrupt_subprocess()
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001069 if self.reading:
1070 self.top.quit() # exit the nested mainloop() in readline()
David Scherer7aced172000-08-15 01:13:23 +00001071 return "break"
1072
1073 def eof_callback(self, event):
1074 if self.executing and not self.reading:
1075 return # Let the default binding (delete next char) take over
1076 if not (self.text.compare("iomark", "==", "insert") and
1077 self.text.compare("insert", "==", "end-1c")):
1078 return # Let the default binding (delete next char) take over
1079 if not self.executing:
David Scherer7aced172000-08-15 01:13:23 +00001080 self.resetoutput()
1081 self.close()
1082 else:
1083 self.canceled = 0
1084 self.endoffile = 1
1085 self.top.quit()
1086 return "break"
1087
David Scherer7aced172000-08-15 01:13:23 +00001088 def linefeed_callback(self, event):
1089 # Insert a linefeed without entering anything (still autoindented)
1090 if self.reading:
1091 self.text.insert("insert", "\n")
1092 self.text.see("insert")
1093 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001094 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001095 return "break"
1096
1097 def enter_callback(self, event):
1098 if self.executing and not self.reading:
1099 return # Let the default binding (insert '\n') take over
1100 # If some text is selected, recall the selection
1101 # (but only if this before the I/O mark)
1102 try:
1103 sel = self.text.get("sel.first", "sel.last")
1104 if sel:
1105 if self.text.compare("sel.last", "<=", "iomark"):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001106 self.recall(sel, event)
David Scherer7aced172000-08-15 01:13:23 +00001107 return "break"
1108 except:
1109 pass
1110 # If we're strictly before the line containing iomark, recall
1111 # the current line, less a leading prompt, less leading or
1112 # trailing whitespace
1113 if self.text.compare("insert", "<", "iomark linestart"):
1114 # Check if there's a relevant stdin range -- if so, use it
1115 prev = self.text.tag_prevrange("stdin", "insert")
1116 if prev and self.text.compare("insert", "<", prev[1]):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001117 self.recall(self.text.get(prev[0], prev[1]), event)
David Scherer7aced172000-08-15 01:13:23 +00001118 return "break"
1119 next = self.text.tag_nextrange("stdin", "insert")
1120 if next and self.text.compare("insert lineend", ">=", next[0]):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001121 self.recall(self.text.get(next[0], next[1]), event)
David Scherer7aced172000-08-15 01:13:23 +00001122 return "break"
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001123 # No stdin mark -- just get the current line, less any prompt
Kurt B. Kaiserb1754452005-11-18 22:05:48 +00001124 indices = self.text.tag_nextrange("console", "insert linestart")
1125 if indices and \
1126 self.text.compare(indices[0], "<=", "insert linestart"):
1127 self.recall(self.text.get(indices[1], "insert lineend"), event)
1128 else:
1129 self.recall(self.text.get("insert linestart", "insert lineend"), event)
David Scherer7aced172000-08-15 01:13:23 +00001130 return "break"
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001131 # If we're between the beginning of the line and the iomark, i.e.
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001132 # in the prompt area, move to the end of the prompt
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001133 if self.text.compare("insert", "<", "iomark"):
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001134 self.text.mark_set("insert", "iomark")
David Scherer7aced172000-08-15 01:13:23 +00001135 # If we're in the current input and there's only whitespace
1136 # beyond the cursor, erase that whitespace first
1137 s = self.text.get("insert", "end-1c")
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001138 if s and not s.strip():
David Scherer7aced172000-08-15 01:13:23 +00001139 self.text.delete("insert", "end-1c")
1140 # If we're in the current input before its last line,
1141 # insert a newline right at the insert point
1142 if self.text.compare("insert", "<", "end-1c linestart"):
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001143 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001144 return "break"
1145 # We're in the last line; append a newline and submit it
1146 self.text.mark_set("insert", "end-1c")
1147 if self.reading:
1148 self.text.insert("insert", "\n")
1149 self.text.see("insert")
1150 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001151 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001152 self.text.tag_add("stdin", "iomark", "end-1c")
1153 self.text.update_idletasks()
1154 if self.reading:
Neal Norwitzce96f692006-03-17 06:49:51 +00001155 self.top.quit() # Break out of recursive mainloop()
David Scherer7aced172000-08-15 01:13:23 +00001156 else:
1157 self.runit()
1158 return "break"
1159
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001160 def recall(self, s, event):
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001161 # remove leading and trailing empty or whitespace lines
1162 s = re.sub(r'^\s*\n', '' , s)
1163 s = re.sub(r'\n\s*$', '', s)
1164 lines = s.split('\n')
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001165 self.text.undo_block_start()
1166 try:
1167 self.text.tag_remove("sel", "1.0", "end")
1168 self.text.mark_set("insert", "end-1c")
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001169 prefix = self.text.get("insert linestart", "insert")
1170 if prefix.rstrip().endswith(':'):
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001171 self.newline_and_indent_event(event)
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001172 prefix = self.text.get("insert linestart", "insert")
1173 self.text.insert("insert", lines[0].strip())
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001174 if len(lines) > 1:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001175 orig_base_indent = re.search(r'^([ \t]*)', lines[0]).group(0)
1176 new_base_indent = re.search(r'^([ \t]*)', prefix).group(0)
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001177 for line in lines[1:]:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001178 if line.startswith(orig_base_indent):
1179 # replace orig base indentation with new indentation
1180 line = new_base_indent + line[len(orig_base_indent):]
1181 self.text.insert('insert', '\n'+line.rstrip())
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001182 finally:
1183 self.text.see("insert")
1184 self.text.undo_block_stop()
David Scherer7aced172000-08-15 01:13:23 +00001185
1186 def runit(self):
1187 line = self.text.get("iomark", "end-1c")
1188 # Strip off last newline and surrounding whitespace.
1189 # (To allow you to hit return twice to end a statement.)
1190 i = len(line)
1191 while i > 0 and line[i-1] in " \t":
1192 i = i-1
1193 if i > 0 and line[i-1] == "\n":
1194 i = i-1
1195 while i > 0 and line[i-1] in " \t":
1196 i = i-1
1197 line = line[:i]
1198 more = self.interp.runsource(line)
David Scherer7aced172000-08-15 01:13:23 +00001199
David Scherer7aced172000-08-15 01:13:23 +00001200 def open_stack_viewer(self, event=None):
Chui Tey5d2af632002-05-26 13:36:41 +00001201 if self.interp.rpcclt:
1202 return self.interp.remote_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +00001203 try:
1204 sys.last_traceback
1205 except:
1206 tkMessageBox.showerror("No stack trace",
1207 "There is no stack trace yet.\n"
1208 "(sys.last_traceback is not defined)",
1209 master=self.text)
1210 return
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +00001211 from idlelib.StackViewer import StackBrowser
David Scherer7aced172000-08-15 01:13:23 +00001212 sv = StackBrowser(self.root, self.flist)
1213
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001214 def view_restart_mark(self, event=None):
1215 self.text.see("iomark")
1216 self.text.see("restart")
1217
1218 def restart_shell(self, event=None):
Terry Jan Reedyda4c4672012-01-31 02:26:32 -05001219 "Callback for Run/Restart Shell Cntl-F6"
1220 self.interp.restart_subprocess(with_cwd=True)
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001221
David Scherer7aced172000-08-15 01:13:23 +00001222 def showprompt(self):
1223 self.resetoutput()
1224 try:
1225 s = str(sys.ps1)
1226 except:
1227 s = ""
1228 self.console.write(s)
1229 self.text.mark_set("insert", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001230 self.set_line_and_column()
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +00001231 self.io.reset_undo()
David Scherer7aced172000-08-15 01:13:23 +00001232
1233 def resetoutput(self):
1234 source = self.text.get("iomark", "end-1c")
1235 if self.history:
1236 self.history.history_store(source)
1237 if self.text.get("end-2c") != "\n":
1238 self.text.insert("end-1c", "\n")
1239 self.text.mark_set("iomark", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001240 self.set_line_and_column()
David Scherer7aced172000-08-15 01:13:23 +00001241
1242 def write(self, s, tags=()):
Andrew Svetlov05bab932012-03-14 13:22:12 -07001243 if isinstance(s, str) and len(s) and max(s) > '\uffff':
1244 # Tk doesn't support outputting non-BMP characters
1245 # Let's assume what printed string is not very long,
1246 # find first non-BMP character and construct informative
1247 # UnicodeEncodeError exception.
1248 for start, char in enumerate(s):
1249 if char > '\uffff':
1250 break
1251 raise UnicodeEncodeError("UCS-2", char, start, start+1,
1252 'Non-BMP character not supported in Tk')
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001253 try:
1254 self.text.mark_gravity("iomark", "right")
Martin v. Löwis30d5e6c2012-07-25 11:32:26 +02001255 count = OutputWindow.write(self, s, tags, "iomark")
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001256 self.text.mark_gravity("iomark", "left")
1257 except:
Kurt B. Kaisercbbe98f2007-08-12 01:52:35 +00001258 raise ###pass # ### 11Aug07 KBK if we are expecting exceptions
1259 # let's find out what they are and be specific.
David Scherer7aced172000-08-15 01:13:23 +00001260 if self.canceled:
1261 self.canceled = 0
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001262 if not use_subprocess:
1263 raise KeyboardInterrupt
Martin v. Löwis30d5e6c2012-07-25 11:32:26 +02001264 return count
David Scherer7aced172000-08-15 01:13:23 +00001265
Andrew Svetlovd1837672012-11-01 22:41:19 +02001266 def rmenu_check_cut(self):
1267 try:
1268 if self.text.compare('sel.first', '<', 'iomark'):
1269 return 'disabled'
1270 except TclError: # no selection, so the index 'sel.first' doesn't exist
1271 return 'disabled'
1272 return super().rmenu_check_cut()
1273
1274 def rmenu_check_paste(self):
1275 if self.text.compare('insert','<','iomark'):
1276 return 'disabled'
1277 return super().rmenu_check_paste()
1278
Serhiy Storchaka39e70a42013-01-25 15:30:58 +02001279class PseudoFile(io.TextIOBase):
David Scherer7aced172000-08-15 01:13:23 +00001280
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001281 def __init__(self, shell, tags, encoding=None):
David Scherer7aced172000-08-15 01:13:23 +00001282 self.shell = shell
1283 self.tags = tags
Serhiy Storchaka39e70a42013-01-25 15:30:58 +02001284 self._encoding = encoding
David Scherer7aced172000-08-15 01:13:23 +00001285
Serhiy Storchaka39e70a42013-01-25 15:30:58 +02001286 @property
1287 def encoding(self):
1288 return self._encoding
David Scherer7aced172000-08-15 01:13:23 +00001289
Serhiy Storchaka39e70a42013-01-25 15:30:58 +02001290 @property
1291 def name(self):
1292 return '<%s>' % self.tags
David Scherer7aced172000-08-15 01:13:23 +00001293
1294 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001295 return True
David Scherer7aced172000-08-15 01:13:23 +00001296
Serhiy Storchaka39e70a42013-01-25 15:30:58 +02001297
1298class PseudoOutputFile(PseudoFile):
1299
1300 def writable(self):
1301 return True
Martin v. Löwisc882b7c2012-07-25 10:47:20 +02001302
1303 def write(self, s):
Serhiy Storchaka39e70a42013-01-25 15:30:58 +02001304 if self.closed:
1305 raise ValueError("write to closed file")
1306 if not isinstance(s, str):
1307 raise TypeError('must be str, not ' + type(s).__name__)
1308 return self.shell.write(s, self.tags)
1309
1310
1311class PseudoInputFile(PseudoFile):
1312
1313 def __init__(self, shell, tags, encoding=None):
1314 PseudoFile.__init__(self, shell, tags, encoding)
1315 self._line_buffer = ''
1316
1317 def readable(self):
1318 return True
1319
1320 def read(self, size=-1):
1321 if self.closed:
1322 raise ValueError("read from closed file")
1323 if size is None:
1324 size = -1
1325 elif not isinstance(size, int):
1326 raise TypeError('must be int, not ' + type(size).__name__)
1327 result = self._line_buffer
1328 self._line_buffer = ''
1329 if size < 0:
1330 while True:
1331 line = self.shell.readline()
1332 if not line: break
1333 result += line
1334 else:
1335 while len(result) < size:
1336 line = self.shell.readline()
1337 if not line: break
1338 result += line
1339 self._line_buffer = result[size:]
1340 result = result[:size]
1341 return result
1342
1343 def readline(self, size=-1):
1344 if self.closed:
1345 raise ValueError("read from closed file")
1346 if size is None:
1347 size = -1
1348 elif not isinstance(size, int):
1349 raise TypeError('must be int, not ' + type(size).__name__)
1350 line = self._line_buffer or self.shell.readline()
1351 if size < 0:
1352 size = len(line)
1353 self._line_buffer = line[size:]
1354 return line[:size]
Martin v. Löwisc882b7c2012-07-25 10:47:20 +02001355
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001356
David Scherer7aced172000-08-15 01:13:23 +00001357usage_msg = """\
David Scherer7aced172000-08-15 01:13:23 +00001358
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001359USAGE: idle [-deins] [-t title] [file]*
1360 idle [-dns] [-t title] (-c cmd | -r file) [arg]*
1361 idle [-dns] [-t title] - [arg]*
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001362
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001363 -h print this help message and exit
Andrew Svetlov9b1e59a2012-10-05 22:12:44 +03001364 -n run IDLE without a subprocess (DEPRECATED,
1365 see Help/IDLE Help for details)
David Scherer7aced172000-08-15 01:13:23 +00001366
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001367The following options will override the IDLE 'settings' configuration:
Kurt B. Kaiser96d88422001-07-17 04:59:01 +00001368
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001369 -e open an edit window
1370 -i open a shell window
1371
1372The following options imply -i and will open a shell:
1373
1374 -c cmd run the command in a shell, or
1375 -r file run script from file
1376
1377 -d enable the debugger
1378 -s run $IDLESTARTUP or $PYTHONSTARTUP before anything else
1379 -t title set title of shell window
1380
1381A default edit window will be bypassed when -c, -r, or - are used.
1382
1383[arg]* are passed to the command (-c) or script (-r) in sys.argv[1:].
1384
1385Examples:
1386
1387idle
1388 Open an edit window or shell depending on IDLE's configuration.
1389
1390idle foo.py foobar.py
1391 Edit the files, also open a shell if configured to start with shell.
1392
1393idle -est "Baz" foo.py
1394 Run $IDLESTARTUP or $PYTHONSTARTUP, edit foo.py, and open a shell
1395 window with the title "Baz".
1396
Neal Norwitz752abd02008-05-13 04:55:24 +00001397idle -c "import sys; print(sys.argv)" "foo"
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001398 Open a shell window and run the command, passing "-c" in sys.argv[0]
1399 and "foo" in sys.argv[1].
1400
1401idle -d -s -r foo.py "Hello World"
1402 Open a shell window, run a startup script, enable the debugger, and
1403 run foo.py, passing "foo.py" in sys.argv[0] and "Hello World" in
1404 sys.argv[1].
1405
Neal Norwitz752abd02008-05-13 04:55:24 +00001406echo "import sys; print(sys.argv)" | idle - "foobar"
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001407 Open a shell window, run the script piped in, passing '' in sys.argv[0]
1408 and "foobar" in sys.argv[1].
David Scherer7aced172000-08-15 01:13:23 +00001409"""
1410
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001411def main():
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001412 global flist, root, use_subprocess
David Scherer7aced172000-08-15 01:13:23 +00001413
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001414 use_subprocess = True
Kurt B. Kaisere866c812009-04-04 21:07:39 +00001415 enable_shell = True
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001416 enable_edit = False
1417 debug = False
1418 cmd = None
1419 script = None
1420 startup = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001421 try:
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001422 opts, args = getopt.getopt(sys.argv[1:], "c:deihnr:st:")
Guido van Rossumb940e112007-01-10 16:19:56 +00001423 except getopt.error as msg:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001424 sys.stderr.write("Error: %s\n" % str(msg))
1425 sys.stderr.write(usage_msg)
1426 sys.exit(2)
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001427 for o, a in opts:
1428 if o == '-c':
1429 cmd = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001430 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001431 if o == '-d':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001432 debug = True
1433 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001434 if o == '-e':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001435 enable_edit = True
Kurt B. Kaisere866c812009-04-04 21:07:39 +00001436 enable_shell = False
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001437 if o == '-h':
1438 sys.stdout.write(usage_msg)
1439 sys.exit()
1440 if o == '-i':
1441 enable_shell = True
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001442 if o == '-n':
Andrew Svetlov9b1e59a2012-10-05 22:12:44 +03001443 print(" Warning: running IDLE without a subprocess is deprecated.",
1444 file=sys.stderr)
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001445 use_subprocess = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001446 if o == '-r':
1447 script = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001448 if os.path.isfile(script):
1449 pass
1450 else:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001451 print("No script file: ", script)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001452 sys.exit()
1453 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001454 if o == '-s':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001455 startup = True
1456 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001457 if o == '-t':
1458 PyShell.shell_title = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001459 enable_shell = True
1460 if args and args[0] == '-':
1461 cmd = sys.stdin.read()
1462 enable_shell = True
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001463 # process sys.argv and sys.path:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001464 for i in range(len(sys.path)):
1465 sys.path[i] = os.path.abspath(sys.path[i])
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001466 if args and args[0] == '-':
1467 sys.argv = [''] + args[1:]
1468 elif cmd:
1469 sys.argv = ['-c'] + args
1470 elif script:
1471 sys.argv = [script] + args
1472 elif args:
1473 enable_edit = True
1474 pathx = []
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001475 for filename in args:
1476 pathx.append(os.path.dirname(filename))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001477 for dir in pathx:
1478 dir = os.path.abspath(dir)
1479 if not dir in sys.path:
1480 sys.path.insert(0, dir)
Kurt B. Kaiserff002b92002-12-21 21:39:11 +00001481 else:
Neal Norwitzd082b6e2007-08-26 23:37:53 +00001482 dir = os.getcwd()
1483 if dir not in sys.path:
Kurt B. Kaiserff002b92002-12-21 21:39:11 +00001484 sys.path.insert(0, dir)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001485 # check the IDLE settings configuration (but command line overrides)
1486 edit_start = idleConf.GetOption('main', 'General',
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001487 'editor-on-startup', type='bool')
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001488 enable_edit = enable_edit or edit_start
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001489 # start editor and/or shell windows:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001490 root = Tk(className="Idle")
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001491
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001492 fixwordbreaks(root)
1493 root.withdraw()
1494 flist = PyShellFileList(root)
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001495 macosxSupport.setupApp(root, flist)
1496
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001497 if enable_edit:
1498 if not (cmd or script):
Andrew Svetlov6b6e4372012-03-20 23:03:26 +02001499 for filename in args[:]:
1500 if flist.open(filename) is None:
1501 # filename is a directory actually, disconsider it
1502 args.remove(filename)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001503 if not args:
1504 flist.new()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001505 if enable_shell:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001506 shell = flist.open_shell()
1507 if not shell:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001508 return # couldn't open shell
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001509
1510 if macosxSupport.runningAsOSXApp() and flist.dict:
1511 # On OSX: when the user has double-clicked on a file that causes
1512 # IDLE to be launched the shell window will open just in front of
1513 # the file she wants to see. Lower the interpreter window when
1514 # there are open files.
1515 shell.top.lower()
1516
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001517 shell = flist.pyshell
1518 # handle remaining options:
1519 if debug:
1520 shell.open_debugger()
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001521 if startup:
1522 filename = os.environ.get("IDLESTARTUP") or \
1523 os.environ.get("PYTHONSTARTUP")
1524 if filename and os.path.isfile(filename):
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001525 shell.interp.execfile(filename)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001526 if shell and cmd or script:
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001527 shell.interp.runcommand("""if 1:
1528 import sys as _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001529 _sys.argv = %r
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001530 del _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001531 \n""" % (sys.argv,))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001532 if cmd:
1533 shell.interp.execsource(cmd)
1534 elif script:
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001535 shell.interp.prepend_syspath(script)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001536 shell.interp.execfile(script)
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001537
Ned Deily4ce92b22011-01-15 04:37:12 +00001538 # Check for problematic OS X Tk versions and print a warning message
1539 # in the IDLE shell window; this is less intrusive than always opening
1540 # a separate window.
1541 tkversionwarning = macosxSupport.tkVersionWarning(root)
1542 if tkversionwarning:
1543 shell.interp.runcommand(''.join(("print('", tkversionwarning, "')")))
1544
Terry Jan Reedycd6b8c62012-05-26 20:23:45 -04001545 while flist.inversedict: # keep IDLE running while files are open.
1546 root.mainloop()
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001547 root.destroy()
1548
David Scherer7aced172000-08-15 01:13:23 +00001549if __name__ == "__main__":
Kurt B. Kaiser9e8b8282003-06-15 17:38:45 +00001550 sys.modules['PyShell'] = sys.modules['__main__']
David Scherer7aced172000-08-15 01:13:23 +00001551 main()