blob: 3b78f38facfd0240b6c0a6c70e5e6e92873f850e [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:
1017 nosub = "==== No Subprocess ===="
Andrew Svetlovcd49d532012-03-25 11:43:02 +03001018 sys.displayhook = rpc.displayhook
1019
Raymond Hettingera2a8e8b2009-01-27 00:28:36 +00001020 self.write("Python %s on %s\n%s\n%s" %
1021 (sys.version, sys.platform, self.COPYRIGHT, nosub))
David Scherer7aced172000-08-15 01:13:23 +00001022 self.showprompt()
Georg Brandl14fc4272008-05-17 18:39:55 +00001023 import tkinter
1024 tkinter._default_root = None # 03Jan04 KBK What's this?
Kurt B. Kaiser76637292004-01-21 22:10:01 +00001025 return True
David Scherer7aced172000-08-15 01:13:23 +00001026
1027 def readline(self):
1028 save = self.reading
1029 try:
1030 self.reading = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001031 self.top.mainloop() # nested mainloop()
David Scherer7aced172000-08-15 01:13:23 +00001032 finally:
1033 self.reading = save
1034 line = self.text.get("iomark", "end-1c")
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001035 if len(line) == 0: # may be EOF if we quit our mainloop with Ctrl-C
1036 line = "\n"
David Scherer7aced172000-08-15 01:13:23 +00001037 self.resetoutput()
1038 if self.canceled:
1039 self.canceled = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001040 if not use_subprocess:
1041 raise KeyboardInterrupt
David Scherer7aced172000-08-15 01:13:23 +00001042 if self.endoffile:
1043 self.endoffile = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001044 line = ""
David Scherer7aced172000-08-15 01:13:23 +00001045 return line
1046
1047 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001048 return True
David Scherer7aced172000-08-15 01:13:23 +00001049
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001050 def cancel_callback(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +00001051 try:
1052 if self.text.compare("sel.first", "!=", "sel.last"):
1053 return # Active selection -- always use default binding
1054 except:
1055 pass
1056 if not (self.executing or self.reading):
1057 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001058 self.interp.write("KeyboardInterrupt\n")
David Scherer7aced172000-08-15 01:13:23 +00001059 self.showprompt()
1060 return "break"
1061 self.endoffile = 0
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001062 self.canceled = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001063 if (self.executing and self.interp.rpcclt):
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +00001064 if self.interp.getdebugger():
1065 self.interp.restart_subprocess()
1066 else:
1067 self.interp.interrupt_subprocess()
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001068 if self.reading:
1069 self.top.quit() # exit the nested mainloop() in readline()
David Scherer7aced172000-08-15 01:13:23 +00001070 return "break"
1071
1072 def eof_callback(self, event):
1073 if self.executing and not self.reading:
1074 return # Let the default binding (delete next char) take over
1075 if not (self.text.compare("iomark", "==", "insert") and
1076 self.text.compare("insert", "==", "end-1c")):
1077 return # Let the default binding (delete next char) take over
1078 if not self.executing:
David Scherer7aced172000-08-15 01:13:23 +00001079 self.resetoutput()
1080 self.close()
1081 else:
1082 self.canceled = 0
1083 self.endoffile = 1
1084 self.top.quit()
1085 return "break"
1086
David Scherer7aced172000-08-15 01:13:23 +00001087 def linefeed_callback(self, event):
1088 # Insert a linefeed without entering anything (still autoindented)
1089 if self.reading:
1090 self.text.insert("insert", "\n")
1091 self.text.see("insert")
1092 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001093 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001094 return "break"
1095
1096 def enter_callback(self, event):
1097 if self.executing and not self.reading:
1098 return # Let the default binding (insert '\n') take over
1099 # If some text is selected, recall the selection
1100 # (but only if this before the I/O mark)
1101 try:
1102 sel = self.text.get("sel.first", "sel.last")
1103 if sel:
1104 if self.text.compare("sel.last", "<=", "iomark"):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001105 self.recall(sel, event)
David Scherer7aced172000-08-15 01:13:23 +00001106 return "break"
1107 except:
1108 pass
1109 # If we're strictly before the line containing iomark, recall
1110 # the current line, less a leading prompt, less leading or
1111 # trailing whitespace
1112 if self.text.compare("insert", "<", "iomark linestart"):
1113 # Check if there's a relevant stdin range -- if so, use it
1114 prev = self.text.tag_prevrange("stdin", "insert")
1115 if prev and self.text.compare("insert", "<", prev[1]):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001116 self.recall(self.text.get(prev[0], prev[1]), event)
David Scherer7aced172000-08-15 01:13:23 +00001117 return "break"
1118 next = self.text.tag_nextrange("stdin", "insert")
1119 if next and self.text.compare("insert lineend", ">=", next[0]):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001120 self.recall(self.text.get(next[0], next[1]), event)
David Scherer7aced172000-08-15 01:13:23 +00001121 return "break"
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001122 # No stdin mark -- just get the current line, less any prompt
Kurt B. Kaiserb1754452005-11-18 22:05:48 +00001123 indices = self.text.tag_nextrange("console", "insert linestart")
1124 if indices and \
1125 self.text.compare(indices[0], "<=", "insert linestart"):
1126 self.recall(self.text.get(indices[1], "insert lineend"), event)
1127 else:
1128 self.recall(self.text.get("insert linestart", "insert lineend"), event)
David Scherer7aced172000-08-15 01:13:23 +00001129 return "break"
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001130 # If we're between the beginning of the line and the iomark, i.e.
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001131 # in the prompt area, move to the end of the prompt
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001132 if self.text.compare("insert", "<", "iomark"):
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001133 self.text.mark_set("insert", "iomark")
David Scherer7aced172000-08-15 01:13:23 +00001134 # If we're in the current input and there's only whitespace
1135 # beyond the cursor, erase that whitespace first
1136 s = self.text.get("insert", "end-1c")
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001137 if s and not s.strip():
David Scherer7aced172000-08-15 01:13:23 +00001138 self.text.delete("insert", "end-1c")
1139 # If we're in the current input before its last line,
1140 # insert a newline right at the insert point
1141 if self.text.compare("insert", "<", "end-1c linestart"):
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001142 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001143 return "break"
1144 # We're in the last line; append a newline and submit it
1145 self.text.mark_set("insert", "end-1c")
1146 if self.reading:
1147 self.text.insert("insert", "\n")
1148 self.text.see("insert")
1149 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001150 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001151 self.text.tag_add("stdin", "iomark", "end-1c")
1152 self.text.update_idletasks()
1153 if self.reading:
Neal Norwitzce96f692006-03-17 06:49:51 +00001154 self.top.quit() # Break out of recursive mainloop()
David Scherer7aced172000-08-15 01:13:23 +00001155 else:
1156 self.runit()
1157 return "break"
1158
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001159 def recall(self, s, event):
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001160 # remove leading and trailing empty or whitespace lines
1161 s = re.sub(r'^\s*\n', '' , s)
1162 s = re.sub(r'\n\s*$', '', s)
1163 lines = s.split('\n')
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001164 self.text.undo_block_start()
1165 try:
1166 self.text.tag_remove("sel", "1.0", "end")
1167 self.text.mark_set("insert", "end-1c")
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001168 prefix = self.text.get("insert linestart", "insert")
1169 if prefix.rstrip().endswith(':'):
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001170 self.newline_and_indent_event(event)
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001171 prefix = self.text.get("insert linestart", "insert")
1172 self.text.insert("insert", lines[0].strip())
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001173 if len(lines) > 1:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001174 orig_base_indent = re.search(r'^([ \t]*)', lines[0]).group(0)
1175 new_base_indent = re.search(r'^([ \t]*)', prefix).group(0)
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001176 for line in lines[1:]:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001177 if line.startswith(orig_base_indent):
1178 # replace orig base indentation with new indentation
1179 line = new_base_indent + line[len(orig_base_indent):]
1180 self.text.insert('insert', '\n'+line.rstrip())
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001181 finally:
1182 self.text.see("insert")
1183 self.text.undo_block_stop()
David Scherer7aced172000-08-15 01:13:23 +00001184
1185 def runit(self):
1186 line = self.text.get("iomark", "end-1c")
1187 # Strip off last newline and surrounding whitespace.
1188 # (To allow you to hit return twice to end a statement.)
1189 i = len(line)
1190 while i > 0 and line[i-1] in " \t":
1191 i = i-1
1192 if i > 0 and line[i-1] == "\n":
1193 i = i-1
1194 while i > 0 and line[i-1] in " \t":
1195 i = i-1
1196 line = line[:i]
1197 more = self.interp.runsource(line)
David Scherer7aced172000-08-15 01:13:23 +00001198
David Scherer7aced172000-08-15 01:13:23 +00001199 def open_stack_viewer(self, event=None):
Chui Tey5d2af632002-05-26 13:36:41 +00001200 if self.interp.rpcclt:
1201 return self.interp.remote_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +00001202 try:
1203 sys.last_traceback
1204 except:
1205 tkMessageBox.showerror("No stack trace",
1206 "There is no stack trace yet.\n"
1207 "(sys.last_traceback is not defined)",
1208 master=self.text)
1209 return
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +00001210 from idlelib.StackViewer import StackBrowser
David Scherer7aced172000-08-15 01:13:23 +00001211 sv = StackBrowser(self.root, self.flist)
1212
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001213 def view_restart_mark(self, event=None):
1214 self.text.see("iomark")
1215 self.text.see("restart")
1216
1217 def restart_shell(self, event=None):
Terry Jan Reedyda4c4672012-01-31 02:26:32 -05001218 "Callback for Run/Restart Shell Cntl-F6"
1219 self.interp.restart_subprocess(with_cwd=True)
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001220
David Scherer7aced172000-08-15 01:13:23 +00001221 def showprompt(self):
1222 self.resetoutput()
1223 try:
1224 s = str(sys.ps1)
1225 except:
1226 s = ""
1227 self.console.write(s)
1228 self.text.mark_set("insert", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001229 self.set_line_and_column()
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +00001230 self.io.reset_undo()
David Scherer7aced172000-08-15 01:13:23 +00001231
1232 def resetoutput(self):
1233 source = self.text.get("iomark", "end-1c")
1234 if self.history:
1235 self.history.history_store(source)
1236 if self.text.get("end-2c") != "\n":
1237 self.text.insert("end-1c", "\n")
1238 self.text.mark_set("iomark", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001239 self.set_line_and_column()
David Scherer7aced172000-08-15 01:13:23 +00001240
1241 def write(self, s, tags=()):
Andrew Svetlov05bab932012-03-14 13:22:12 -07001242 if isinstance(s, str) and len(s) and max(s) > '\uffff':
1243 # Tk doesn't support outputting non-BMP characters
1244 # Let's assume what printed string is not very long,
1245 # find first non-BMP character and construct informative
1246 # UnicodeEncodeError exception.
1247 for start, char in enumerate(s):
1248 if char > '\uffff':
1249 break
1250 raise UnicodeEncodeError("UCS-2", char, start, start+1,
1251 'Non-BMP character not supported in Tk')
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001252 try:
1253 self.text.mark_gravity("iomark", "right")
Martin v. Löwis30d5e6c2012-07-25 11:32:26 +02001254 count = OutputWindow.write(self, s, tags, "iomark")
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001255 self.text.mark_gravity("iomark", "left")
1256 except:
Kurt B. Kaisercbbe98f2007-08-12 01:52:35 +00001257 raise ###pass # ### 11Aug07 KBK if we are expecting exceptions
1258 # let's find out what they are and be specific.
David Scherer7aced172000-08-15 01:13:23 +00001259 if self.canceled:
1260 self.canceled = 0
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001261 if not use_subprocess:
1262 raise KeyboardInterrupt
Martin v. Löwis30d5e6c2012-07-25 11:32:26 +02001263 return count
David Scherer7aced172000-08-15 01:13:23 +00001264
Andrew Svetlovd1837672012-11-01 22:41:19 +02001265 def rmenu_check_cut(self):
1266 try:
1267 if self.text.compare('sel.first', '<', 'iomark'):
1268 return 'disabled'
1269 except TclError: # no selection, so the index 'sel.first' doesn't exist
1270 return 'disabled'
1271 return super().rmenu_check_cut()
1272
1273 def rmenu_check_paste(self):
1274 if self.text.compare('insert','<','iomark'):
1275 return 'disabled'
1276 return super().rmenu_check_paste()
1277
Kurt B. Kaiserdcba6622004-12-21 22:10:32 +00001278class PseudoFile(object):
David Scherer7aced172000-08-15 01:13:23 +00001279
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001280 def __init__(self, shell, tags, encoding=None):
David Scherer7aced172000-08-15 01:13:23 +00001281 self.shell = shell
1282 self.tags = tags
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001283 self.encoding = encoding
David Scherer7aced172000-08-15 01:13:23 +00001284
1285 def write(self, s):
Martin v. Löwis9ae3f7a2012-07-09 20:46:11 +02001286 if not isinstance(s, str):
1287 raise TypeError('must be str, not ' + type(s).__name__)
Martin v. Löwis30d5e6c2012-07-25 11:32:26 +02001288 return self.shell.write(s, self.tags)
David Scherer7aced172000-08-15 01:13:23 +00001289
Kurt B. Kaiser66aaf742007-08-09 18:00:23 +00001290 def writelines(self, lines):
1291 for line in lines:
1292 self.write(line)
David Scherer7aced172000-08-15 01:13:23 +00001293
1294 def flush(self):
1295 pass
1296
1297 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001298 return True
David Scherer7aced172000-08-15 01:13:23 +00001299
Martin v. Löwisc882b7c2012-07-25 10:47:20 +02001300class PseudoInputFile(object):
1301 def __init__(self, shell):
1302 self.readline = shell.readline
1303 self.isatty = shell.isatty
1304
1305 def write(self, s):
1306 raise io.UnsupportedOperation("not writable")
1307 writelines = write
1308
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001309
David Scherer7aced172000-08-15 01:13:23 +00001310usage_msg = """\
David Scherer7aced172000-08-15 01:13:23 +00001311
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001312USAGE: idle [-deins] [-t title] [file]*
1313 idle [-dns] [-t title] (-c cmd | -r file) [arg]*
1314 idle [-dns] [-t title] - [arg]*
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001315
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001316 -h print this help message and exit
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001317 -n run IDLE without a subprocess (see Help/IDLE Help for details)
David Scherer7aced172000-08-15 01:13:23 +00001318
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001319The following options will override the IDLE 'settings' configuration:
Kurt B. Kaiser96d88422001-07-17 04:59:01 +00001320
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001321 -e open an edit window
1322 -i open a shell window
1323
1324The following options imply -i and will open a shell:
1325
1326 -c cmd run the command in a shell, or
1327 -r file run script from file
1328
1329 -d enable the debugger
1330 -s run $IDLESTARTUP or $PYTHONSTARTUP before anything else
1331 -t title set title of shell window
1332
1333A default edit window will be bypassed when -c, -r, or - are used.
1334
1335[arg]* are passed to the command (-c) or script (-r) in sys.argv[1:].
1336
1337Examples:
1338
1339idle
1340 Open an edit window or shell depending on IDLE's configuration.
1341
1342idle foo.py foobar.py
1343 Edit the files, also open a shell if configured to start with shell.
1344
1345idle -est "Baz" foo.py
1346 Run $IDLESTARTUP or $PYTHONSTARTUP, edit foo.py, and open a shell
1347 window with the title "Baz".
1348
Neal Norwitz752abd02008-05-13 04:55:24 +00001349idle -c "import sys; print(sys.argv)" "foo"
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001350 Open a shell window and run the command, passing "-c" in sys.argv[0]
1351 and "foo" in sys.argv[1].
1352
1353idle -d -s -r foo.py "Hello World"
1354 Open a shell window, run a startup script, enable the debugger, and
1355 run foo.py, passing "foo.py" in sys.argv[0] and "Hello World" in
1356 sys.argv[1].
1357
Neal Norwitz752abd02008-05-13 04:55:24 +00001358echo "import sys; print(sys.argv)" | idle - "foobar"
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001359 Open a shell window, run the script piped in, passing '' in sys.argv[0]
1360 and "foobar" in sys.argv[1].
David Scherer7aced172000-08-15 01:13:23 +00001361"""
1362
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001363def main():
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001364 global flist, root, use_subprocess
David Scherer7aced172000-08-15 01:13:23 +00001365
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001366 use_subprocess = True
Kurt B. Kaisere866c812009-04-04 21:07:39 +00001367 enable_shell = True
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001368 enable_edit = False
1369 debug = False
1370 cmd = None
1371 script = None
1372 startup = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001373 try:
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001374 opts, args = getopt.getopt(sys.argv[1:], "c:deihnr:st:")
Guido van Rossumb940e112007-01-10 16:19:56 +00001375 except getopt.error as msg:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001376 sys.stderr.write("Error: %s\n" % str(msg))
1377 sys.stderr.write(usage_msg)
1378 sys.exit(2)
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001379 for o, a in opts:
1380 if o == '-c':
1381 cmd = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001382 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001383 if o == '-d':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001384 debug = True
1385 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001386 if o == '-e':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001387 enable_edit = True
Kurt B. Kaisere866c812009-04-04 21:07:39 +00001388 enable_shell = False
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001389 if o == '-h':
1390 sys.stdout.write(usage_msg)
1391 sys.exit()
1392 if o == '-i':
1393 enable_shell = True
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001394 if o == '-n':
1395 use_subprocess = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001396 if o == '-r':
1397 script = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001398 if os.path.isfile(script):
1399 pass
1400 else:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001401 print("No script file: ", script)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001402 sys.exit()
1403 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001404 if o == '-s':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001405 startup = True
1406 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001407 if o == '-t':
1408 PyShell.shell_title = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001409 enable_shell = True
1410 if args and args[0] == '-':
1411 cmd = sys.stdin.read()
1412 enable_shell = True
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001413 # process sys.argv and sys.path:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001414 for i in range(len(sys.path)):
1415 sys.path[i] = os.path.abspath(sys.path[i])
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001416 if args and args[0] == '-':
1417 sys.argv = [''] + args[1:]
1418 elif cmd:
1419 sys.argv = ['-c'] + args
1420 elif script:
1421 sys.argv = [script] + args
1422 elif args:
1423 enable_edit = True
1424 pathx = []
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001425 for filename in args:
1426 pathx.append(os.path.dirname(filename))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001427 for dir in pathx:
1428 dir = os.path.abspath(dir)
1429 if not dir in sys.path:
1430 sys.path.insert(0, dir)
Kurt B. Kaiserff002b92002-12-21 21:39:11 +00001431 else:
Neal Norwitzd082b6e2007-08-26 23:37:53 +00001432 dir = os.getcwd()
1433 if dir not in sys.path:
Kurt B. Kaiserff002b92002-12-21 21:39:11 +00001434 sys.path.insert(0, dir)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001435 # check the IDLE settings configuration (but command line overrides)
1436 edit_start = idleConf.GetOption('main', 'General',
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001437 'editor-on-startup', type='bool')
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001438 enable_edit = enable_edit or edit_start
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001439 # start editor and/or shell windows:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001440 root = Tk(className="Idle")
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001441
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001442 fixwordbreaks(root)
1443 root.withdraw()
1444 flist = PyShellFileList(root)
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001445 macosxSupport.setupApp(root, flist)
1446
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001447 if enable_edit:
1448 if not (cmd or script):
Andrew Svetlov6b6e4372012-03-20 23:03:26 +02001449 for filename in args[:]:
1450 if flist.open(filename) is None:
1451 # filename is a directory actually, disconsider it
1452 args.remove(filename)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001453 if not args:
1454 flist.new()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001455 if enable_shell:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001456 shell = flist.open_shell()
1457 if not shell:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001458 return # couldn't open shell
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001459
1460 if macosxSupport.runningAsOSXApp() and flist.dict:
1461 # On OSX: when the user has double-clicked on a file that causes
1462 # IDLE to be launched the shell window will open just in front of
1463 # the file she wants to see. Lower the interpreter window when
1464 # there are open files.
1465 shell.top.lower()
1466
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001467 shell = flist.pyshell
1468 # handle remaining options:
1469 if debug:
1470 shell.open_debugger()
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001471 if startup:
1472 filename = os.environ.get("IDLESTARTUP") or \
1473 os.environ.get("PYTHONSTARTUP")
1474 if filename and os.path.isfile(filename):
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001475 shell.interp.execfile(filename)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001476 if shell and cmd or script:
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001477 shell.interp.runcommand("""if 1:
1478 import sys as _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001479 _sys.argv = %r
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001480 del _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001481 \n""" % (sys.argv,))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001482 if cmd:
1483 shell.interp.execsource(cmd)
1484 elif script:
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001485 shell.interp.prepend_syspath(script)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001486 shell.interp.execfile(script)
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001487
Ned Deily4ce92b22011-01-15 04:37:12 +00001488 # Check for problematic OS X Tk versions and print a warning message
1489 # in the IDLE shell window; this is less intrusive than always opening
1490 # a separate window.
1491 tkversionwarning = macosxSupport.tkVersionWarning(root)
1492 if tkversionwarning:
1493 shell.interp.runcommand(''.join(("print('", tkversionwarning, "')")))
1494
Terry Jan Reedycd6b8c62012-05-26 20:23:45 -04001495 while flist.inversedict: # keep IDLE running while files are open.
1496 root.mainloop()
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001497 root.destroy()
1498
David Scherer7aced172000-08-15 01:13:23 +00001499if __name__ == "__main__":
Kurt B. Kaiser9e8b8282003-06-15 17:38:45 +00001500 sys.modules['PyShell'] = sys.modules['__main__']
David Scherer7aced172000-08-15 01:13:23 +00001501 main()