blob: 1ae69499bc439f4a9fa0513992d7827cdf2ca9df [file] [log] [blame]
David Scherer7aced172000-08-15 01:13:23 +00001#! /usr/bin/env python
2
David Scherer7aced172000-08-15 01:13:23 +00003import os
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +00004import os.path
David Scherer7aced172000-08-15 01:13:23 +00005import sys
6import string
7import getopt
8import re
Chui Tey5d2af632002-05-26 13:36:41 +00009import socket
10import time
Kurt B. Kaiser003091c2003-02-17 18:57:16 +000011import threading
Chui Tey5d2af632002-05-26 13:36:41 +000012import traceback
Kurt B. Kaiser62833982002-09-18 17:07:05 +000013import types
Martin v. Löwise2b56242012-07-25 10:56:22 +020014import io
David Scherer7aced172000-08-15 01:13:23 +000015
16import linecache
17from code import InteractiveInterpreter
Terry Jan Reedyd676a3a2013-03-30 18:50:43 -040018from platform import python_version
David Scherer7aced172000-08-15 01:13:23 +000019
Kurt B. Kaiser2303b1c2003-11-24 05:26:16 +000020try:
Georg Brandl6634bf22008-05-20 07:13:37 +000021 from Tkinter import *
Kurt B. Kaiser2303b1c2003-11-24 05:26:16 +000022except ImportError:
Georg Brandl6634bf22008-05-20 07:13:37 +000023 print>>sys.__stderr__, "** IDLE can't import Tkinter. " \
Kurt B. Kaiser2303b1c2003-11-24 05:26:16 +000024 "Your Python may not be configured for Tk. **"
25 sys.exit(1)
Georg Brandl6634bf22008-05-20 07:13:37 +000026import tkMessageBox
David Scherer7aced172000-08-15 01:13:23 +000027
Florent Xiclunad630c042010-04-02 07:24:52 +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. Kaiserb9764192002-09-23 04:10:37 +000040IDENTCHARS = string.ascii_letters + string.digits + "_"
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +000041HOST = '127.0.0.1' # python execution server on localhost loopback
42PORT = 0 # someday pass in host, port for remote debug capability
Kurt B. Kaiserb9764192002-09-23 04:10:37 +000043
Kurt B. Kaisera00050f2003-05-08 20:26:55 +000044try:
45 from signal import SIGTERM
46except ImportError:
47 SIGTERM = 15
48
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000049# Override warnings module to write to warning_stream. Initialize to send IDLE
50# internal warnings to the console. ScriptBinding.check_syntax() will
51# temporarily redirect the stream to the shell window to display warnings when
52# checking user's code.
53global warning_stream
54warning_stream = sys.__stderr__
Chui Tey5d2af632002-05-26 13:36:41 +000055try:
56 import warnings
57except ImportError:
58 pass
59else:
Benjamin Petersonb76444b2008-10-16 19:40:14 +000060 def idle_showwarning(message, category, filename, lineno,
61 file=None, line=None):
Guilherme Polof198ac22009-08-14 14:03:07 +000062 if file is None:
63 file = warning_stream
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000064 try:
Guilherme Polof198ac22009-08-14 14:03:07 +000065 file.write(warnings.formatwarning(message, category, filename,
Senthil Kumaran13502b12011-07-03 17:38:53 -070066 lineno, line=line))
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000067 except IOError:
68 pass ## file (probably __stderr__) is invalid, warning dropped.
Chui Tey5d2af632002-05-26 13:36:41 +000069 warnings.showwarning = idle_showwarning
Guilherme Polof198ac22009-08-14 14:03:07 +000070 def idle_formatwarning(message, category, filename, lineno, line=None):
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000071 """Format warnings the IDLE way"""
72 s = "\nWarning (from warnings module):\n"
73 s += ' File \"%s\", line %s\n' % (filename, lineno)
Guilherme Polof198ac22009-08-14 14:03:07 +000074 if line is None:
75 line = linecache.getline(filename, lineno)
76 line = line.strip()
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000077 if line:
78 s += " %s\n" % line
79 s += "%s: %s\n>>> " % (category.__name__, message)
80 return s
81 warnings.formatwarning = idle_formatwarning
Chui Tey5d2af632002-05-26 13:36:41 +000082
Kurt B. Kaiserf7a88992004-11-13 21:05:58 +000083def extended_linecache_checkcache(filename=None,
84 orig_checkcache=linecache.checkcache):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +000085 """Extend linecache.checkcache to preserve the <pyshell#...> entries
86
Kurt B. Kaiserf7a88992004-11-13 21:05:58 +000087 Rather than repeating the linecache code, patch it to save the
88 <pyshell#...> entries, call the original linecache.checkcache()
Guilherme Polof198ac22009-08-14 14:03:07 +000089 (skipping them), and then restore the saved entries.
Kurt B. Kaiserf7a88992004-11-13 21:05:58 +000090
91 orig_checkcache is bound at definition time to the original
92 method, allowing it to be patched.
Kurt B. Kaiser45186c42002-10-23 04:48:08 +000093 """
David Scherer7aced172000-08-15 01:13:23 +000094 cache = linecache.cache
95 save = {}
Guilherme Polof198ac22009-08-14 14:03:07 +000096 for key in list(cache):
97 if key[:1] + key[-1:] == '<>':
98 save[key] = cache.pop(key)
99 orig_checkcache(filename)
David Scherer7aced172000-08-15 01:13:23 +0000100 cache.update(save)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000101
Kurt B. Kaiser81885592002-11-29 22:10:53 +0000102# Patch linecache.checkcache():
103linecache.checkcache = extended_linecache_checkcache
David Scherer7aced172000-08-15 01:13:23 +0000104
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000105
David Scherer7aced172000-08-15 01:13:23 +0000106class PyShellEditorWindow(EditorWindow):
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000107 "Regular text edit window in IDLE, supports breakpoints"
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000108
David Scherer7aced172000-08-15 01:13:23 +0000109 def __init__(self, *args):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000110 self.breakpoints = []
Raymond Hettinger931237e2003-07-09 18:48:24 +0000111 EditorWindow.__init__(self, *args)
David Scherer7aced172000-08-15 01:13:23 +0000112 self.text.bind("<<set-breakpoint-here>>", self.set_breakpoint_here)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000113 self.text.bind("<<clear-breakpoint-here>>", self.clear_breakpoint_here)
David Scherer7aced172000-08-15 01:13:23 +0000114 self.text.bind("<<open-python-shell>>", self.flist.open_shell)
115
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000116 self.breakpointPath = os.path.join(idleConf.GetUserCfgDir(),
117 'breakpoints.lst')
Chui Teya2adb0f2002-11-04 22:14:54 +0000118 # whenever a file is changed, restore breakpoints
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000119 def filename_changed_hook(old_hook=self.io.filename_change_hook,
120 self=self):
Chui Teya2adb0f2002-11-04 22:14:54 +0000121 self.restore_file_breaks()
122 old_hook()
123 self.io.set_filename_change_hook(filename_changed_hook)
Roger Serwyd7c9d9c2013-04-02 22:37:12 -0500124 if self.io.filename:
125 self.restore_file_breaks()
Chui Teya2adb0f2002-11-04 22:14:54 +0000126
Andrew Svetlov5018db72012-11-01 22:39:14 +0200127 rmenu_specs = [
128 ("Cut", "<<cut>>", "rmenu_check_cut"),
129 ("Copy", "<<copy>>", "rmenu_check_copy"),
130 ("Paste", "<<paste>>", "rmenu_check_paste"),
131 ("Set Breakpoint", "<<set-breakpoint-here>>", None),
132 ("Clear Breakpoint", "<<clear-breakpoint-here>>", None)
133 ]
David Scherer7aced172000-08-15 01:13:23 +0000134
Chui Teya2adb0f2002-11-04 22:14:54 +0000135 def set_breakpoint(self, lineno):
136 text = self.text
137 filename = self.io.filename
138 text.tag_add("BREAK", "%d.0" % lineno, "%d.0" % (lineno+1))
139 try:
140 i = self.breakpoints.index(lineno)
141 except ValueError: # only add if missing, i.e. do once
142 self.breakpoints.append(lineno)
143 try: # update the subprocess debugger
144 debug = self.flist.pyshell.interp.debugger
145 debug.set_breakpoint_here(filename, lineno)
146 except: # but debugger may not be active right now....
147 pass
148
David Scherer7aced172000-08-15 01:13:23 +0000149 def set_breakpoint_here(self, event=None):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000150 text = self.text
151 filename = self.io.filename
152 if not filename:
153 text.bell()
David Scherer7aced172000-08-15 01:13:23 +0000154 return
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000155 lineno = int(float(text.index("insert")))
Chui Teya2adb0f2002-11-04 22:14:54 +0000156 self.set_breakpoint(lineno)
David Scherer7aced172000-08-15 01:13:23 +0000157
Kurt B. Kaiser669f4c32002-06-20 04:01:47 +0000158 def clear_breakpoint_here(self, event=None):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000159 text = self.text
160 filename = self.io.filename
161 if not filename:
162 text.bell()
Kurt B. Kaiser669f4c32002-06-20 04:01:47 +0000163 return
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000164 lineno = int(float(text.index("insert")))
165 try:
166 self.breakpoints.remove(lineno)
167 except:
168 pass
169 text.tag_remove("BREAK", "insert linestart",\
170 "insert lineend +1char")
171 try:
172 debug = self.flist.pyshell.interp.debugger
173 debug.clear_breakpoint_here(filename, lineno)
174 except:
175 pass
176
177 def clear_file_breaks(self):
178 if self.breakpoints:
179 text = self.text
180 filename = self.io.filename
181 if not filename:
182 text.bell()
183 return
184 self.breakpoints = []
185 text.tag_remove("BREAK", "1.0", END)
186 try:
187 debug = self.flist.pyshell.interp.debugger
188 debug.clear_file_breaks(filename)
189 except:
190 pass
191
Chui Teya2adb0f2002-11-04 22:14:54 +0000192 def store_file_breaks(self):
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000193 "Save breakpoints when file is saved"
194 # XXX 13 Dec 2002 KBK Currently the file must be saved before it can
195 # be run. The breaks are saved at that time. If we introduce
196 # a temporary file save feature the save breaks functionality
197 # needs to be re-verified, since the breaks at the time the
198 # temp file is created may differ from the breaks at the last
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000199 # permanent save of the file. Currently, a break introduced
200 # after a save will be effective, but not persistent.
201 # This is necessary to keep the saved breaks synched with the
202 # saved file.
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000203 #
204 # Breakpoints are set as tagged ranges in the text. Certain
205 # kinds of edits cause these ranges to be deleted: Inserting
206 # or deleting a line just before a breakpoint, and certain
207 # deletions prior to a breakpoint. These issues need to be
208 # investigated and understood. It's not clear if they are
209 # Tk issues or IDLE issues, or whether they can actually
210 # be fixed. Since a modified file has to be saved before it is
211 # run, and since self.breakpoints (from which the subprocess
212 # debugger is loaded) is updated during the save, the visible
213 # breaks stay synched with the subprocess even if one of these
214 # unexpected breakpoint deletions occurs.
215 breaks = self.breakpoints
216 filename = self.io.filename
Chui Teya2adb0f2002-11-04 22:14:54 +0000217 try:
Ned Deily40ad0412011-12-14 14:57:43 -0800218 with open(self.breakpointPath,"r") as old_file:
219 lines = old_file.readlines()
Chui Teya2adb0f2002-11-04 22:14:54 +0000220 except IOError:
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000221 lines = []
Ned Deily40ad0412011-12-14 14:57:43 -0800222 try:
223 with open(self.breakpointPath,"w") as new_file:
224 for line in lines:
225 if not line.startswith(filename + '='):
226 new_file.write(line)
227 self.update_breakpoints()
228 breaks = self.breakpoints
229 if breaks:
230 new_file.write(filename + '=' + str(breaks) + '\n')
231 except IOError as err:
232 if not getattr(self.root, "breakpoint_error_displayed", False):
233 self.root.breakpoint_error_displayed = True
234 tkMessageBox.showerror(title='IDLE Error',
235 message='Unable to update breakpoint list:\n%s'
236 % str(err),
237 parent=self.text)
Chui Teya2adb0f2002-11-04 22:14:54 +0000238
239 def restore_file_breaks(self):
240 self.text.update() # this enables setting "BREAK" tags to be visible
Roger Serwyd7c9d9c2013-04-02 22:37:12 -0500241 if self.io is None:
242 # can happen if IDLE closes due to the .update() call
243 return
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000244 filename = self.io.filename
245 if filename is None:
246 return
Chui Tey69371d62002-11-04 23:39:45 +0000247 if os.path.isfile(self.breakpointPath):
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000248 lines = open(self.breakpointPath,"r").readlines()
Chui Tey69371d62002-11-04 23:39:45 +0000249 for line in lines:
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000250 if line.startswith(filename + '='):
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000251 breakpoint_linenumbers = eval(line[len(filename)+1:])
Chui Tey69371d62002-11-04 23:39:45 +0000252 for breakpoint_linenumber in breakpoint_linenumbers:
253 self.set_breakpoint(breakpoint_linenumber)
Chui Teya2adb0f2002-11-04 22:14:54 +0000254
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000255 def update_breakpoints(self):
256 "Retrieves all the breakpoints in the current window"
Chui Teya2adb0f2002-11-04 22:14:54 +0000257 text = self.text
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000258 ranges = text.tag_ranges("BREAK")
259 linenumber_list = self.ranges_to_linenumbers(ranges)
260 self.breakpoints = linenumber_list
261
262 def ranges_to_linenumbers(self, ranges):
263 lines = []
264 for index in range(0, len(ranges), 2):
Andrew Svetlov8a15c372012-07-31 19:51:27 +0300265 lineno = int(float(ranges[index].string))
266 end = int(float(ranges[index+1].string))
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000267 while lineno < end:
268 lines.append(lineno)
269 lineno += 1
270 return lines
271
Kurt B. Kaiser11220fa2002-12-24 00:57:22 +0000272# XXX 13 Dec 2002 KBK Not used currently
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000273# def saved_change_hook(self):
274# "Extend base method - clear breaks if module is modified"
275# if not self.get_saved():
276# self.clear_file_breaks()
277# EditorWindow.saved_change_hook(self)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000278
279 def _close(self):
280 "Extend base method - clear breaks when module is closed"
281 self.clear_file_breaks()
282 EditorWindow._close(self)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000283
David Scherer7aced172000-08-15 01:13:23 +0000284
285class PyShellFileList(FileList):
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000286 "Extend base class: IDLE supports a shell and breakpoints"
David Scherer7aced172000-08-15 01:13:23 +0000287
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000288 # override FileList's class variable, instances return PyShellEditorWindow
289 # instead of EditorWindow when new edit windows are created.
David Scherer7aced172000-08-15 01:13:23 +0000290 EditorWindow = PyShellEditorWindow
291
292 pyshell = None
293
294 def open_shell(self, event=None):
295 if self.pyshell:
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000296 self.pyshell.top.wakeup()
David Scherer7aced172000-08-15 01:13:23 +0000297 else:
298 self.pyshell = PyShell(self)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000299 if self.pyshell:
300 if not self.pyshell.begin():
301 return None
David Scherer7aced172000-08-15 01:13:23 +0000302 return self.pyshell
303
304
305class ModifiedColorDelegator(ColorDelegator):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000306 "Extend base class: colorizer for the shell window itself"
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000307
Steven M. Gavab77d3432002-03-02 07:16:21 +0000308 def __init__(self):
309 ColorDelegator.__init__(self)
310 self.LoadTagDefs()
David Scherer7aced172000-08-15 01:13:23 +0000311
312 def recolorize_main(self):
313 self.tag_remove("TODO", "1.0", "iomark")
314 self.tag_add("SYNC", "1.0", "iomark")
315 ColorDelegator.recolorize_main(self)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000316
Steven M. Gavab77d3432002-03-02 07:16:21 +0000317 def LoadTagDefs(self):
318 ColorDelegator.LoadTagDefs(self)
319 theme = idleConf.GetOption('main','Theme','name')
320 self.tagdefs.update({
321 "stdin": {'background':None,'foreground':None},
322 "stdout": idleConf.GetHighlight(theme, "stdout"),
323 "stderr": idleConf.GetHighlight(theme, "stderr"),
324 "console": idleConf.GetHighlight(theme, "console"),
Steven M. Gavab77d3432002-03-02 07:16:21 +0000325 })
David Scherer7aced172000-08-15 01:13:23 +0000326
Ned Deily5e247b72012-05-31 09:17:29 -0700327 def removecolors(self):
328 # Don't remove shell color tags before "iomark"
329 for tag in self.tagdefs:
330 self.tag_remove(tag, "iomark", "end")
331
David Scherer7aced172000-08-15 01:13:23 +0000332class ModifiedUndoDelegator(UndoDelegator):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000333 "Extend base class: forbid insert/delete before the I/O mark"
David Scherer7aced172000-08-15 01:13:23 +0000334
335 def insert(self, index, chars, tags=None):
336 try:
337 if self.delegate.compare(index, "<", "iomark"):
338 self.delegate.bell()
339 return
340 except TclError:
341 pass
342 UndoDelegator.insert(self, index, chars, tags)
343
344 def delete(self, index1, index2=None):
345 try:
346 if self.delegate.compare(index1, "<", "iomark"):
347 self.delegate.bell()
348 return
349 except TclError:
350 pass
351 UndoDelegator.delete(self, index1, index2)
352
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000353
354class MyRPCClient(rpc.RPCClient):
355
356 def handle_EOF(self):
357 "Override the base class - just re-raise EOFError"
358 raise EOFError
359
Kurt B. Kaiser8d1f11b2003-05-26 22:20:34 +0000360
David Scherer7aced172000-08-15 01:13:23 +0000361class ModifiedInterpreter(InteractiveInterpreter):
362
363 def __init__(self, tkconsole):
364 self.tkconsole = tkconsole
365 locals = sys.modules['__main__'].__dict__
366 InteractiveInterpreter.__init__(self, locals=locals)
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000367 self.save_warnings_filters = None
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000368 self.restarting = False
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +0000369 self.subprocess_arglist = None
370 self.port = PORT
Ned Deily86d669b2011-10-30 19:58:04 -0700371 self.original_compiler_flags = self.compile.compiler.flags
David Scherer7aced172000-08-15 01:13:23 +0000372
Roger Serwy16ce43a2013-06-11 22:13:17 -0500373 _afterid = None
Chui Tey5d2af632002-05-26 13:36:41 +0000374 rpcclt = None
375 rpcpid = None
376
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000377 def spawn_subprocess(self):
Florent Xiclunac8a730b2010-03-25 20:32:07 +0000378 if self.subprocess_arglist is None:
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +0000379 self.subprocess_arglist = self.build_subprocess_arglist()
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000380 args = self.subprocess_arglist
Kurt B. Kaiserb7855182003-08-14 14:54:28 +0000381 self.rpcpid = os.spawnv(os.P_NOWAIT, sys.executable, args)
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000382
Tony Lowndsf53dec22002-12-20 04:24:43 +0000383 def build_subprocess_arglist(self):
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +0000384 assert (self.port!=0), (
385 "Socket should have been assigned a port number.")
Tony Lownds2398d572003-05-13 15:28:21 +0000386 w = ['-W' + s for s in sys.warnoptions]
Georg Brandld0761532006-10-12 07:57:21 +0000387 if 1/2 > 0: # account for new division
388 w.append('-Qnew')
Tony Lownds2398d572003-05-13 15:28:21 +0000389 # Maybe IDLE is installed and is being accessed via sys.path,
390 # or maybe it's not installed and the idle.py script is being
391 # run from the IDLE source directory.
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000392 del_exitf = idleConf.GetOption('main', 'General', 'delete-exitfunc',
393 default=False, type='bool')
Tony Lownds2398d572003-05-13 15:28:21 +0000394 if __name__ == 'idlelib.PyShell':
Walter Dörwald70a6b492004-02-12 17:35:32 +0000395 command = "__import__('idlelib.run').run.main(%r)" % (del_exitf,)
Tony Lowndsf2324b92002-09-29 00:34:10 +0000396 else:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000397 command = "__import__('run').main(%r)" % (del_exitf,)
Kurt B. Kaiserb7855182003-08-14 14:54:28 +0000398 if sys.platform[:3] == 'win' and ' ' in sys.executable:
399 # handle embedded space in path by quoting the argument
400 decorated_exec = '"%s"' % sys.executable
401 else:
402 decorated_exec = sys.executable
403 return [decorated_exec] + w + ["-c", command, str(self.port)]
Tony Lowndsf2324b92002-09-29 00:34:10 +0000404
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000405 def start_subprocess(self):
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +0000406 addr = (HOST, self.port)
407 # GUI makes several attempts to acquire socket, listens for connection
Kurt B. Kaiser5db48432003-05-15 03:40:51 +0000408 for i in range(3):
Chui Tey5d2af632002-05-26 13:36:41 +0000409 time.sleep(i)
410 try:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000411 self.rpcclt = MyRPCClient(addr)
Chui Tey5d2af632002-05-26 13:36:41 +0000412 break
413 except socket.error, err:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000414 pass
Chui Tey5d2af632002-05-26 13:36:41 +0000415 else:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000416 self.display_port_binding_error()
417 return None
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +0000418 # if PORT was 0, system will assign an 'ephemeral' port. Find it out:
419 self.port = self.rpcclt.listening_sock.getsockname()[1]
420 # if PORT was not 0, probably working with a remote execution server
421 if PORT != 0:
422 # To allow reconnection within the 2MSL wait (cf. Stevens TCP
423 # V1, 18.6), set SO_REUSEADDR. Note that this can be problematic
424 # on Windows since the implementation allows two active sockets on
425 # the same address!
426 self.rpcclt.listening_sock.setsockopt(socket.SOL_SOCKET,
427 socket.SO_REUSEADDR, 1)
428 self.spawn_subprocess()
429 #time.sleep(20) # test to simulate GUI not accepting connection
Kurt B. Kaiserb4179362002-07-26 00:06:42 +0000430 # Accept the connection from the Python execution server
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000431 self.rpcclt.listening_sock.settimeout(10)
432 try:
433 self.rpcclt.accept()
434 except socket.timeout, err:
435 self.display_no_subprocess_error()
436 return None
Serhiy Storchaka9abc8302013-01-25 15:30:35 +0200437 self.rpcclt.register("console", self.tkconsole)
438 self.rpcclt.register("stdin", self.tkconsole.stdin)
Kurt B. Kaiser969de452002-06-12 03:28:57 +0000439 self.rpcclt.register("stdout", self.tkconsole.stdout)
440 self.rpcclt.register("stderr", self.tkconsole.stderr)
Chui Tey5d2af632002-05-26 13:36:41 +0000441 self.rpcclt.register("flist", self.tkconsole.flist)
Kurt B. Kaiser8cd0def2003-01-31 05:06:43 +0000442 self.rpcclt.register("linecache", linecache)
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000443 self.rpcclt.register("interp", self)
Terry Jan Reedyb98000a2012-01-31 02:09:25 -0500444 self.transfer_path(with_cwd=True)
Chui Tey5d2af632002-05-26 13:36:41 +0000445 self.poll_subprocess()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000446 return self.rpcclt
Chui Tey5d2af632002-05-26 13:36:41 +0000447
Terry Jan Reedyb98000a2012-01-31 02:09:25 -0500448 def restart_subprocess(self, with_cwd=False):
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000449 if self.restarting:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000450 return self.rpcclt
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000451 self.restarting = True
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000452 # close only the subprocess debugger
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000453 debug = self.getdebugger()
454 if debug:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000455 try:
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000456 # Only close subprocess debugger, don't unregister gui_adap!
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000457 RemoteDebugger.close_subprocess_debugger(self.rpcclt)
458 except:
459 pass
460 # Kill subprocess, spawn a new one, accept connection.
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000461 self.rpcclt.close()
462 self.unix_terminate()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000463 console = self.tkconsole
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000464 was_executing = console.executing
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000465 console.executing = False
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000466 self.spawn_subprocess()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000467 try:
468 self.rpcclt.accept()
469 except socket.timeout, err:
470 self.display_no_subprocess_error()
471 return None
Terry Jan Reedyb98000a2012-01-31 02:09:25 -0500472 self.transfer_path(with_cwd=with_cwd)
Roger Serwyad8cad32013-04-03 00:42:24 -0500473 console.stop_readline()
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000474 # annotate restart in shell window and mark it
Kurt B. Kaiser4cc5ef52003-01-22 00:23:23 +0000475 console.text.delete("iomark", "end-1c")
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000476 if was_executing:
477 console.write('\n')
478 console.showprompt()
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000479 halfbar = ((int(console.width) - 16) // 2) * '='
480 console.write(halfbar + ' RESTART ' + halfbar)
481 console.text.mark_set("restart", "end-1c")
482 console.text.mark_gravity("restart", "left")
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000483 console.showprompt()
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000484 # restart subprocess debugger
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000485 if debug:
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000486 # Restarted debugger connects to current instance of debug GUI
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000487 gui = RemoteDebugger.restart_subprocess_debugger(self.rpcclt)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000488 # reload remote debugger breakpoints for all PyShellEditWindows
489 debug.load_breakpoints()
Ned Deily86d669b2011-10-30 19:58:04 -0700490 self.compile.compiler.flags = self.original_compiler_flags
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000491 self.restarting = False
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000492 return self.rpcclt
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000493
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000494 def __request_interrupt(self):
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000495 self.rpcclt.remotecall("exec", "interrupt_the_server", (), {})
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000496
497 def interrupt_subprocess(self):
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000498 threading.Thread(target=self.__request_interrupt).start()
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000499
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000500 def kill_subprocess(self):
Roger Serwy16ce43a2013-06-11 22:13:17 -0500501 if self._afterid is not None:
502 self.tkconsole.text.after_cancel(self._afterid)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000503 try:
504 self.rpcclt.close()
505 except AttributeError: # no socket
506 pass
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000507 self.unix_terminate()
508 self.tkconsole.executing = False
509 self.rpcclt = None
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000510
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000511 def unix_terminate(self):
512 "UNIX: make sure subprocess is terminated and collect status"
513 if hasattr(os, 'kill'):
514 try:
515 os.kill(self.rpcpid, SIGTERM)
516 except OSError:
517 # process already terminated:
518 return
519 else:
520 try:
521 os.waitpid(self.rpcpid, 0)
522 except OSError:
523 return
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000524
Terry Jan Reedyb98000a2012-01-31 02:09:25 -0500525 def transfer_path(self, with_cwd=False):
526 if with_cwd: # Issue 13506
527 path = [''] # include Current Working Directory
528 path.extend(sys.path)
529 else:
530 path = sys.path
Terry Jan Reedy1d4ae482012-01-31 02:55:32 -0500531
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000532 self.runcommand("""if 1:
533 import sys as _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +0000534 _sys.path = %r
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000535 del _sys
Terry Jan Reedyb98000a2012-01-31 02:09:25 -0500536 \n""" % (path,))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000537
Chui Tey5d2af632002-05-26 13:36:41 +0000538 active_seq = None
539
540 def poll_subprocess(self):
541 clt = self.rpcclt
542 if clt is None:
543 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000544 try:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000545 response = clt.pollresponse(self.active_seq, wait=0.05)
546 except (EOFError, IOError, KeyboardInterrupt):
547 # lost connection or subprocess terminated itself, restart
548 # [the KBI is from rpc.SocketIO.handle_EOF()]
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000549 if self.tkconsole.closing:
550 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000551 response = None
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000552 self.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000553 if response:
554 self.tkconsole.resetoutput()
555 self.active_seq = None
556 how, what = response
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000557 console = self.tkconsole.console
Chui Tey5d2af632002-05-26 13:36:41 +0000558 if how == "OK":
559 if what is not None:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000560 print >>console, repr(what)
Chui Tey5d2af632002-05-26 13:36:41 +0000561 elif how == "EXCEPTION":
Chui Tey5d2af632002-05-26 13:36:41 +0000562 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
563 self.remote_stack_viewer()
564 elif how == "ERROR":
Kurt B. Kaiser0930c432002-12-06 21:45:24 +0000565 errmsg = "PyShell.ModifiedInterpreter: Subprocess ERROR:\n"
566 print >>sys.__stderr__, errmsg, what
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000567 print >>console, errmsg, what
568 # we received a response to the currently active seq number:
Kurt B. Kaiserd112bc72006-08-16 05:01:42 +0000569 try:
570 self.tkconsole.endexecuting()
571 except AttributeError: # shell may have closed
572 pass
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000573 # Reschedule myself
574 if not self.tkconsole.closing:
Roger Serwy16ce43a2013-06-11 22:13:17 -0500575 self._afterid = self.tkconsole.text.after(
576 self.tkconsole.pollinterval, self.poll_subprocess)
Chui Tey5d2af632002-05-26 13:36:41 +0000577
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000578 debugger = None
579
580 def setdebugger(self, debugger):
581 self.debugger = debugger
582
583 def getdebugger(self):
584 return self.debugger
585
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000586 def open_remote_stack_viewer(self):
587 """Initiate the remote stack viewer from a separate thread.
588
589 This method is called from the subprocess, and by returning from this
590 method we allow the subprocess to unblock. After a bit the shell
591 requests the subprocess to open the remote stack viewer which returns a
Ezio Melottic569cfe2010-07-23 16:55:21 +0000592 static object looking at the last exception. It is queried through
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000593 the RPC mechanism.
594
595 """
596 self.tkconsole.text.after(300, self.remote_stack_viewer)
597 return
598
Chui Tey5d2af632002-05-26 13:36:41 +0000599 def remote_stack_viewer(self):
Florent Xiclunad630c042010-04-02 07:24:52 +0000600 from idlelib import RemoteObjectBrowser
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000601 oid = self.rpcclt.remotequeue("exec", "stackviewer", ("flist",), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000602 if oid is None:
603 self.tkconsole.root.bell()
604 return
605 item = RemoteObjectBrowser.StubObjectTreeItem(self.rpcclt, oid)
Florent Xiclunad630c042010-04-02 07:24:52 +0000606 from idlelib.TreeWidget import ScrolledCanvas, TreeNode
Chui Tey5d2af632002-05-26 13:36:41 +0000607 top = Toplevel(self.tkconsole.root)
Kurt B. Kaiser73360a32004-03-08 18:15:31 +0000608 theme = idleConf.GetOption('main','Theme','name')
609 background = idleConf.GetHighlight(theme, 'normal')['background']
610 sc = ScrolledCanvas(top, bg=background, highlightthickness=0)
Chui Tey5d2af632002-05-26 13:36:41 +0000611 sc.frame.pack(expand=1, fill="both")
612 node = TreeNode(sc.canvas, None, item)
613 node.expand()
614 # XXX Should GC the remote tree when closing the window
615
David Scherer7aced172000-08-15 01:13:23 +0000616 gid = 0
617
618 def execsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000619 "Like runsource() but assumes complete exec source"
David Scherer7aced172000-08-15 01:13:23 +0000620 filename = self.stuffsource(source)
621 self.execfile(filename, source)
622
623 def execfile(self, filename, source=None):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000624 "Execute an existing file"
David Scherer7aced172000-08-15 01:13:23 +0000625 if source is None:
626 source = open(filename, "r").read()
627 try:
628 code = compile(source, filename, "exec")
629 except (OverflowError, SyntaxError):
630 self.tkconsole.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000631 tkerr = self.tkconsole.stderr
632 print>>tkerr, '*** Error in script or command!\n'
633 print>>tkerr, 'Traceback (most recent call last):'
David Scherer7aced172000-08-15 01:13:23 +0000634 InteractiveInterpreter.showsyntaxerror(self, filename)
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000635 self.tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000636 else:
637 self.runcode(code)
638
639 def runsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000640 "Extend base class method: Stuff the source in the line cache first"
David Scherer7aced172000-08-15 01:13:23 +0000641 filename = self.stuffsource(source)
642 self.more = 0
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000643 self.save_warnings_filters = warnings.filters[:]
644 warnings.filterwarnings(action="error", category=SyntaxWarning)
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000645 if isinstance(source, types.UnicodeType):
Florent Xiclunad630c042010-04-02 07:24:52 +0000646 from idlelib import IOBinding
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000647 try:
648 source = source.encode(IOBinding.encoding)
649 except UnicodeError:
650 self.tkconsole.resetoutput()
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +0000651 self.write("Unsupported characters in input\n")
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000652 return
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000653 try:
Kurt B. Kaiser935ea9a2005-05-10 03:44:24 +0000654 # InteractiveInterpreter.runsource() calls its runcode() method,
655 # which is overridden (see below)
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000656 return InteractiveInterpreter.runsource(self, source, filename)
657 finally:
658 if self.save_warnings_filters is not None:
659 warnings.filters[:] = self.save_warnings_filters
660 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000661
662 def stuffsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000663 "Stuff source in the filename cache"
David Scherer7aced172000-08-15 01:13:23 +0000664 filename = "<pyshell#%d>" % self.gid
665 self.gid = self.gid + 1
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000666 lines = source.split("\n")
David Scherer7aced172000-08-15 01:13:23 +0000667 linecache.cache[filename] = len(source)+1, 0, lines, filename
668 return filename
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000669
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000670 def prepend_syspath(self, filename):
671 "Prepend sys.path with file's directory if not already included"
672 self.runcommand("""if 1:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000673 _filename = %r
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000674 import sys as _sys
675 from os.path import dirname as _dirname
676 _dir = _dirname(_filename)
677 if not _dir in _sys.path:
678 _sys.path.insert(0, _dir)
679 del _filename, _sys, _dirname, _dir
Walter Dörwald70a6b492004-02-12 17:35:32 +0000680 \n""" % (filename,))
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000681
David Scherer7aced172000-08-15 01:13:23 +0000682 def showsyntaxerror(self, filename=None):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000683 """Extend base class method: Add Colorizing
684
685 Color the offending position instead of printing it and pointing at it
686 with a caret.
687
688 """
David Scherer7aced172000-08-15 01:13:23 +0000689 text = self.tkconsole.text
690 stuff = self.unpackerror()
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000691 if stuff:
692 msg, lineno, offset, line = stuff
693 if lineno == 1:
694 pos = "iomark + %d chars" % (offset-1)
695 else:
696 pos = "iomark linestart + %d lines + %d chars" % \
697 (lineno-1, offset-1)
698 text.tag_add("ERROR", pos)
699 text.see(pos)
700 char = text.get(pos)
701 if char and char in IDENTCHARS:
702 text.tag_add("ERROR", pos + " wordstart", pos)
703 self.tkconsole.resetoutput()
704 self.write("SyntaxError: %s\n" % str(msg))
705 else:
David Scherer7aced172000-08-15 01:13:23 +0000706 self.tkconsole.resetoutput()
707 InteractiveInterpreter.showsyntaxerror(self, filename)
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000708 self.tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000709
710 def unpackerror(self):
711 type, value, tb = sys.exc_info()
712 ok = type is SyntaxError
713 if ok:
714 try:
715 msg, (dummy_filename, lineno, offset, line) = value
Kurt B. Kaiserbea57c62003-07-09 04:27:24 +0000716 if not offset:
717 offset = 0
David Scherer7aced172000-08-15 01:13:23 +0000718 except:
719 ok = 0
720 if ok:
721 return msg, lineno, offset, line
722 else:
723 return None
724
725 def showtraceback(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000726 "Extend base class method to reset output properly"
David Scherer7aced172000-08-15 01:13:23 +0000727 self.tkconsole.resetoutput()
728 self.checklinecache()
729 InteractiveInterpreter.showtraceback(self)
Chui Tey5d2af632002-05-26 13:36:41 +0000730 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
731 self.tkconsole.open_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +0000732
733 def checklinecache(self):
734 c = linecache.cache
735 for key in c.keys():
736 if key[:1] + key[-1:] != "<>":
737 del c[key]
738
Chui Tey5d2af632002-05-26 13:36:41 +0000739 def runcommand(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000740 "Run the code without invoking the debugger"
Chui Tey5d2af632002-05-26 13:36:41 +0000741 # The code better not raise an exception!
742 if self.tkconsole.executing:
Neal Norwitzf4c4f112002-11-30 18:49:10 +0000743 self.display_executing_dialog()
Chui Tey5d2af632002-05-26 13:36:41 +0000744 return 0
745 if self.rpcclt:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000746 self.rpcclt.remotequeue("exec", "runcode", (code,), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000747 else:
748 exec code in self.locals
749 return 1
750
David Scherer7aced172000-08-15 01:13:23 +0000751 def runcode(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000752 "Override base class method"
Chui Tey5d2af632002-05-26 13:36:41 +0000753 if self.tkconsole.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000754 self.interp.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000755 self.checklinecache()
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000756 if self.save_warnings_filters is not None:
757 warnings.filters[:] = self.save_warnings_filters
758 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000759 debugger = self.debugger
760 try:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000761 self.tkconsole.beginexecuting()
Kurt B. Kaiserdddeb0e2007-02-06 03:21:40 +0000762 if not debugger and self.rpcclt is not None:
763 self.active_seq = self.rpcclt.asyncqueue("exec", "runcode",
764 (code,), {})
765 elif debugger:
766 debugger.run(code, self.locals)
767 else:
768 exec code in self.locals
769 except SystemExit:
770 if not self.tkconsole.closing:
771 if tkMessageBox.askyesno(
772 "Exit?",
773 "Do you want to exit altogether?",
774 default="yes",
775 master=self.tkconsole.text):
Kurt B. Kaiserf137e1d2006-08-16 07:04:17 +0000776 raise
Kurt B. Kaiserdddeb0e2007-02-06 03:21:40 +0000777 else:
778 self.showtraceback()
779 else:
780 raise
781 except:
782 if use_subprocess:
783 print >>self.tkconsole.stderr, \
784 "IDLE internal error in runcode()"
David Scherer7aced172000-08-15 01:13:23 +0000785 self.showtraceback()
Kurt B. Kaiserdddeb0e2007-02-06 03:21:40 +0000786 self.tkconsole.endexecuting()
787 else:
788 if self.tkconsole.canceled:
789 self.tkconsole.canceled = False
790 print >>self.tkconsole.stderr, "KeyboardInterrupt"
791 else:
792 self.showtraceback()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000793 finally:
794 if not use_subprocess:
Kurt B. Kaiserd112bc72006-08-16 05:01:42 +0000795 try:
796 self.tkconsole.endexecuting()
797 except AttributeError: # shell may have closed
798 pass
David Scherer7aced172000-08-15 01:13:23 +0000799
800 def write(self, s):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000801 "Override base class method"
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000802 self.tkconsole.stderr.write(s)
David Scherer7aced172000-08-15 01:13:23 +0000803
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000804 def display_port_binding_error(self):
805 tkMessageBox.showerror(
806 "Port Binding Error",
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +0000807 "IDLE can't bind to a TCP/IP port, which is necessary to "
808 "communicate with its Python execution server. This might be "
809 "because no networking is installed on this computer. "
810 "Run IDLE with the -n command line switch to start without a "
811 "subprocess and refer to Help/IDLE Help 'Running without a "
812 "subprocess' for further details.",
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000813 master=self.tkconsole.text)
814
815 def display_no_subprocess_error(self):
816 tkMessageBox.showerror(
817 "Subprocess Startup Error",
818 "IDLE's subprocess didn't make connection. Either IDLE can't "
819 "start a subprocess or personal firewall software is blocking "
820 "the connection.",
821 master=self.tkconsole.text)
822
823 def display_executing_dialog(self):
824 tkMessageBox.showerror(
825 "Already executing",
826 "The Python Shell window is already executing a command; "
827 "please wait until it is finished.",
828 master=self.tkconsole.text)
829
830
David Scherer7aced172000-08-15 01:13:23 +0000831class PyShell(OutputWindow):
832
Terry Jan Reedyd676a3a2013-03-30 18:50:43 -0400833 shell_title = "Python " + python_version() + " Shell"
David Scherer7aced172000-08-15 01:13:23 +0000834
835 # Override classes
836 ColorDelegator = ModifiedColorDelegator
837 UndoDelegator = ModifiedUndoDelegator
838
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000839 # Override menus
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000840 menu_specs = [
841 ("file", "_File"),
842 ("edit", "_Edit"),
Kurt B. Kaiser4cc5ef52003-01-22 00:23:23 +0000843 ("debug", "_Debug"),
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000844 ("options", "_Options"),
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000845 ("windows", "_Windows"),
846 ("help", "_Help"),
847 ]
David Scherer7aced172000-08-15 01:13:23 +0000848
Ronald Oussoren19302d92006-06-11 14:33:36 +0000849 if macosxSupport.runningAsOSXApp():
Ronald Oussoren19302d92006-06-11 14:33:36 +0000850 menu_specs[-2] = ("windows", "_Window")
851
852
David Scherer7aced172000-08-15 01:13:23 +0000853 # New classes
Florent Xiclunad630c042010-04-02 07:24:52 +0000854 from idlelib.IdleHistory import History
David Scherer7aced172000-08-15 01:13:23 +0000855
856 def __init__(self, flist=None):
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000857 if use_subprocess:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000858 ms = self.menu_specs
859 if ms[2][0] != "shell":
Kurt B. Kaiser7ae35482006-08-16 21:45:59 +0000860 ms.insert(2, ("shell", "She_ll"))
David Scherer7aced172000-08-15 01:13:23 +0000861 self.interp = ModifiedInterpreter(self)
862 if flist is None:
863 root = Tk()
864 fixwordbreaks(root)
865 root.withdraw()
866 flist = PyShellFileList(root)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000867 #
David Scherer7aced172000-08-15 01:13:23 +0000868 OutputWindow.__init__(self, flist, None, None)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000869 #
Kurt B. Kaiser6af44982005-01-19 00:22:59 +0000870## self.config(usetabs=1, indentwidth=8, context_use_ps1=1)
871 self.usetabs = True
872 # indentwidth must be 8 when using tabs. See note in EditorWindow:
873 self.indentwidth = 8
874 self.context_use_ps1 = True
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000875 #
David Scherer7aced172000-08-15 01:13:23 +0000876 text = self.text
877 text.configure(wrap="char")
878 text.bind("<<newline-and-indent>>", self.enter_callback)
879 text.bind("<<plain-newline-and-indent>>", self.linefeed_callback)
880 text.bind("<<interrupt-execution>>", self.cancel_callback)
David Scherer7aced172000-08-15 01:13:23 +0000881 text.bind("<<end-of-file>>", self.eof_callback)
882 text.bind("<<open-stack-viewer>>", self.open_stack_viewer)
Kurt B. Kaiser57bfe5d2003-05-10 00:09:52 +0000883 text.bind("<<toggle-debugger>>", self.toggle_debugger)
David Scherer7aced172000-08-15 01:13:23 +0000884 text.bind("<<toggle-jit-stack-viewer>>", self.toggle_jit_stack_viewer)
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000885 if use_subprocess:
886 text.bind("<<view-restart>>", self.view_restart_mark)
887 text.bind("<<restart-shell>>", self.restart_shell)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000888 #
David Scherer7aced172000-08-15 01:13:23 +0000889 self.save_stdout = sys.stdout
890 self.save_stderr = sys.stderr
891 self.save_stdin = sys.stdin
Florent Xiclunad630c042010-04-02 07:24:52 +0000892 from idlelib import IOBinding
Serhiy Storchaka9abc8302013-01-25 15:30:35 +0200893 self.stdin = PseudoInputFile(self, "stdin", IOBinding.encoding)
894 self.stdout = PseudoOutputFile(self, "stdout", IOBinding.encoding)
895 self.stderr = PseudoOutputFile(self, "stderr", IOBinding.encoding)
896 self.console = PseudoOutputFile(self, "console", IOBinding.encoding)
Chui Tey5d2af632002-05-26 13:36:41 +0000897 if not use_subprocess:
898 sys.stdout = self.stdout
899 sys.stderr = self.stderr
Martin v. Löwise2b56242012-07-25 10:56:22 +0200900 sys.stdin = self.stdin
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000901 #
David Scherer7aced172000-08-15 01:13:23 +0000902 self.history = self.History(self.text)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000903 #
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000904 self.pollinterval = 50 # millisec
Chui Tey5d2af632002-05-26 13:36:41 +0000905
Kurt B. Kaiser4d5bc602004-06-06 01:29:22 +0000906 def get_standard_extension_names(self):
907 return idleConf.GetExtensions(shell_only=True)
908
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000909 reading = False
910 executing = False
911 canceled = False
912 endoffile = False
913 closing = False
Roger Serwyad8cad32013-04-03 00:42:24 -0500914 _stop_readline_flag = False
David Scherer7aced172000-08-15 01:13:23 +0000915
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +0000916 def set_warning_stream(self, stream):
Skip Montanarod9161422004-07-06 21:53:27 +0000917 global warning_stream
918 warning_stream = stream
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +0000919
920 def get_warning_stream(self):
921 return warning_stream
922
David Scherer7aced172000-08-15 01:13:23 +0000923 def toggle_debugger(self, event=None):
924 if self.executing:
925 tkMessageBox.showerror("Don't debug now",
926 "You can only toggle the debugger when idle",
927 master=self.text)
928 self.set_debugger_indicator()
929 return "break"
930 else:
931 db = self.interp.getdebugger()
932 if db:
933 self.close_debugger()
934 else:
935 self.open_debugger()
936
937 def set_debugger_indicator(self):
938 db = self.interp.getdebugger()
939 self.setvar("<<toggle-debugger>>", not not db)
940
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000941 def toggle_jit_stack_viewer(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +0000942 pass # All we need is the variable
943
944 def close_debugger(self):
945 db = self.interp.getdebugger()
946 if db:
947 self.interp.setdebugger(None)
948 db.close()
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000949 if self.interp.rpcclt:
950 RemoteDebugger.close_remote_debugger(self.interp.rpcclt)
David Scherer7aced172000-08-15 01:13:23 +0000951 self.resetoutput()
952 self.console.write("[DEBUG OFF]\n")
953 sys.ps1 = ">>> "
954 self.showprompt()
955 self.set_debugger_indicator()
956
957 def open_debugger(self):
Chui Tey5d2af632002-05-26 13:36:41 +0000958 if self.interp.rpcclt:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000959 dbg_gui = RemoteDebugger.start_remote_debugger(self.interp.rpcclt,
960 self)
961 else:
962 dbg_gui = Debugger.Debugger(self)
963 self.interp.setdebugger(dbg_gui)
964 dbg_gui.load_breakpoints()
Chui Tey5d2af632002-05-26 13:36:41 +0000965 sys.ps1 = "[DEBUG ON]\n>>> "
966 self.showprompt()
967 self.set_debugger_indicator()
968
David Scherer7aced172000-08-15 01:13:23 +0000969 def beginexecuting(self):
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000970 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +0000971 self.resetoutput()
972 self.executing = 1
David Scherer7aced172000-08-15 01:13:23 +0000973
974 def endexecuting(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000975 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +0000976 self.executing = 0
977 self.canceled = 0
Chui Tey5d2af632002-05-26 13:36:41 +0000978 self.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000979
980 def close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000981 "Extend EditorWindow.close()"
David Scherer7aced172000-08-15 01:13:23 +0000982 if self.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000983 response = tkMessageBox.askokcancel(
David Scherer7aced172000-08-15 01:13:23 +0000984 "Kill?",
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000985 "The program is still running!\n Do you want to kill it?",
David Scherer7aced172000-08-15 01:13:23 +0000986 default="ok",
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000987 parent=self.text)
Benjamin Peterson5b63acd2008-03-29 15:24:25 +0000988 if response is False:
David Scherer7aced172000-08-15 01:13:23 +0000989 return "cancel"
Roger Serwyad8cad32013-04-03 00:42:24 -0500990 self.stop_readline()
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +0000991 self.canceled = True
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000992 self.closing = True
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000993 return EditorWindow.close(self)
David Scherer7aced172000-08-15 01:13:23 +0000994
995 def _close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000996 "Extend EditorWindow._close(), shut down debugger and execution server"
David Scherer7aced172000-08-15 01:13:23 +0000997 self.close_debugger()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000998 if use_subprocess:
999 self.interp.kill_subprocess()
David Scherer7aced172000-08-15 01:13:23 +00001000 # Restore std streams
1001 sys.stdout = self.save_stdout
1002 sys.stderr = self.save_stderr
1003 sys.stdin = self.save_stdin
1004 # Break cycles
1005 self.interp = None
1006 self.console = None
David Scherer7aced172000-08-15 01:13:23 +00001007 self.flist.pyshell = None
1008 self.history = None
Kurt B. Kaiser83118c62002-06-24 17:03:37 +00001009 EditorWindow._close(self)
David Scherer7aced172000-08-15 01:13:23 +00001010
1011 def ispythonsource(self, filename):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +00001012 "Override EditorWindow method: never remove the colorizer"
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001013 return True
David Scherer7aced172000-08-15 01:13:23 +00001014
1015 def short_title(self):
1016 return self.shell_title
1017
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +00001018 COPYRIGHT = \
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001019 'Type "copyright", "credits" or "license()" for more information.'
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +00001020
David Scherer7aced172000-08-15 01:13:23 +00001021 def begin(self):
1022 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001023 if use_subprocess:
1024 nosub = ''
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001025 client = self.interp.start_subprocess()
1026 if not client:
1027 self.close()
Kurt B. Kaiser76637292004-01-21 22:10:01 +00001028 return False
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001029 else:
1030 nosub = "==== No Subprocess ===="
Raymond Hettingerbf3f69e2009-01-26 23:29:09 +00001031 self.write("Python %s on %s\n%s\n%s" %
1032 (sys.version, sys.platform, self.COPYRIGHT, nosub))
David Scherer7aced172000-08-15 01:13:23 +00001033 self.showprompt()
Georg Brandl6634bf22008-05-20 07:13:37 +00001034 import Tkinter
1035 Tkinter._default_root = None # 03Jan04 KBK What's this?
Kurt B. Kaiser76637292004-01-21 22:10:01 +00001036 return True
David Scherer7aced172000-08-15 01:13:23 +00001037
Roger Serwyad8cad32013-04-03 00:42:24 -05001038 def stop_readline(self):
1039 if not self.reading: # no nested mainloop to exit.
1040 return
1041 self._stop_readline_flag = True
1042 self.top.quit()
1043
David Scherer7aced172000-08-15 01:13:23 +00001044 def readline(self):
1045 save = self.reading
1046 try:
1047 self.reading = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001048 self.top.mainloop() # nested mainloop()
David Scherer7aced172000-08-15 01:13:23 +00001049 finally:
1050 self.reading = save
Roger Serwyad8cad32013-04-03 00:42:24 -05001051 if self._stop_readline_flag:
1052 self._stop_readline_flag = False
1053 return ""
David Scherer7aced172000-08-15 01:13:23 +00001054 line = self.text.get("iomark", "end-1c")
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001055 if len(line) == 0: # may be EOF if we quit our mainloop with Ctrl-C
1056 line = "\n"
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001057 if isinstance(line, unicode):
Florent Xiclunad630c042010-04-02 07:24:52 +00001058 from idlelib import IOBinding
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001059 try:
1060 line = line.encode(IOBinding.encoding)
1061 except UnicodeError:
1062 pass
David Scherer7aced172000-08-15 01:13:23 +00001063 self.resetoutput()
1064 if self.canceled:
1065 self.canceled = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001066 if not use_subprocess:
1067 raise KeyboardInterrupt
David Scherer7aced172000-08-15 01:13:23 +00001068 if self.endoffile:
1069 self.endoffile = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001070 line = ""
David Scherer7aced172000-08-15 01:13:23 +00001071 return line
1072
1073 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001074 return True
David Scherer7aced172000-08-15 01:13:23 +00001075
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001076 def cancel_callback(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +00001077 try:
1078 if self.text.compare("sel.first", "!=", "sel.last"):
1079 return # Active selection -- always use default binding
1080 except:
1081 pass
1082 if not (self.executing or self.reading):
1083 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001084 self.interp.write("KeyboardInterrupt\n")
David Scherer7aced172000-08-15 01:13:23 +00001085 self.showprompt()
1086 return "break"
1087 self.endoffile = 0
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001088 self.canceled = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001089 if (self.executing and self.interp.rpcclt):
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +00001090 if self.interp.getdebugger():
1091 self.interp.restart_subprocess()
1092 else:
1093 self.interp.interrupt_subprocess()
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001094 if self.reading:
1095 self.top.quit() # exit the nested mainloop() in readline()
David Scherer7aced172000-08-15 01:13:23 +00001096 return "break"
1097
1098 def eof_callback(self, event):
1099 if self.executing and not self.reading:
1100 return # Let the default binding (delete next char) take over
1101 if not (self.text.compare("iomark", "==", "insert") and
1102 self.text.compare("insert", "==", "end-1c")):
1103 return # Let the default binding (delete next char) take over
1104 if not self.executing:
David Scherer7aced172000-08-15 01:13:23 +00001105 self.resetoutput()
1106 self.close()
1107 else:
1108 self.canceled = 0
1109 self.endoffile = 1
1110 self.top.quit()
1111 return "break"
1112
David Scherer7aced172000-08-15 01:13:23 +00001113 def linefeed_callback(self, event):
1114 # Insert a linefeed without entering anything (still autoindented)
1115 if self.reading:
1116 self.text.insert("insert", "\n")
1117 self.text.see("insert")
1118 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001119 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001120 return "break"
1121
1122 def enter_callback(self, event):
1123 if self.executing and not self.reading:
1124 return # Let the default binding (insert '\n') take over
1125 # If some text is selected, recall the selection
1126 # (but only if this before the I/O mark)
1127 try:
1128 sel = self.text.get("sel.first", "sel.last")
1129 if sel:
1130 if self.text.compare("sel.last", "<=", "iomark"):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001131 self.recall(sel, event)
David Scherer7aced172000-08-15 01:13:23 +00001132 return "break"
1133 except:
1134 pass
1135 # If we're strictly before the line containing iomark, recall
1136 # the current line, less a leading prompt, less leading or
1137 # trailing whitespace
1138 if self.text.compare("insert", "<", "iomark linestart"):
1139 # Check if there's a relevant stdin range -- if so, use it
1140 prev = self.text.tag_prevrange("stdin", "insert")
1141 if prev and self.text.compare("insert", "<", prev[1]):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001142 self.recall(self.text.get(prev[0], prev[1]), event)
David Scherer7aced172000-08-15 01:13:23 +00001143 return "break"
1144 next = self.text.tag_nextrange("stdin", "insert")
1145 if next and self.text.compare("insert lineend", ">=", next[0]):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001146 self.recall(self.text.get(next[0], next[1]), event)
David Scherer7aced172000-08-15 01:13:23 +00001147 return "break"
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001148 # No stdin mark -- just get the current line, less any prompt
Kurt B. Kaiserb1754452005-11-18 22:05:48 +00001149 indices = self.text.tag_nextrange("console", "insert linestart")
1150 if indices and \
1151 self.text.compare(indices[0], "<=", "insert linestart"):
1152 self.recall(self.text.get(indices[1], "insert lineend"), event)
1153 else:
1154 self.recall(self.text.get("insert linestart", "insert lineend"), event)
David Scherer7aced172000-08-15 01:13:23 +00001155 return "break"
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001156 # If we're between the beginning of the line and the iomark, i.e.
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001157 # in the prompt area, move to the end of the prompt
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001158 if self.text.compare("insert", "<", "iomark"):
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001159 self.text.mark_set("insert", "iomark")
David Scherer7aced172000-08-15 01:13:23 +00001160 # If we're in the current input and there's only whitespace
1161 # beyond the cursor, erase that whitespace first
1162 s = self.text.get("insert", "end-1c")
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001163 if s and not s.strip():
David Scherer7aced172000-08-15 01:13:23 +00001164 self.text.delete("insert", "end-1c")
1165 # If we're in the current input before its last line,
1166 # insert a newline right at the insert point
1167 if self.text.compare("insert", "<", "end-1c linestart"):
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001168 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001169 return "break"
1170 # We're in the last line; append a newline and submit it
1171 self.text.mark_set("insert", "end-1c")
1172 if self.reading:
1173 self.text.insert("insert", "\n")
1174 self.text.see("insert")
1175 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001176 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001177 self.text.tag_add("stdin", "iomark", "end-1c")
1178 self.text.update_idletasks()
1179 if self.reading:
1180 self.top.quit() # Break out of recursive mainloop() in raw_input()
1181 else:
1182 self.runit()
1183 return "break"
1184
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001185 def recall(self, s, event):
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001186 # remove leading and trailing empty or whitespace lines
1187 s = re.sub(r'^\s*\n', '' , s)
1188 s = re.sub(r'\n\s*$', '', s)
1189 lines = s.split('\n')
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001190 self.text.undo_block_start()
1191 try:
1192 self.text.tag_remove("sel", "1.0", "end")
1193 self.text.mark_set("insert", "end-1c")
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001194 prefix = self.text.get("insert linestart", "insert")
1195 if prefix.rstrip().endswith(':'):
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001196 self.newline_and_indent_event(event)
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001197 prefix = self.text.get("insert linestart", "insert")
1198 self.text.insert("insert", lines[0].strip())
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001199 if len(lines) > 1:
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001200 orig_base_indent = re.search(r'^([ \t]*)', lines[0]).group(0)
1201 new_base_indent = re.search(r'^([ \t]*)', prefix).group(0)
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001202 for line in lines[1:]:
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001203 if line.startswith(orig_base_indent):
1204 # replace orig base indentation with new indentation
1205 line = new_base_indent + line[len(orig_base_indent):]
1206 self.text.insert('insert', '\n'+line.rstrip())
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001207 finally:
1208 self.text.see("insert")
1209 self.text.undo_block_stop()
David Scherer7aced172000-08-15 01:13:23 +00001210
1211 def runit(self):
1212 line = self.text.get("iomark", "end-1c")
1213 # Strip off last newline and surrounding whitespace.
1214 # (To allow you to hit return twice to end a statement.)
1215 i = len(line)
1216 while i > 0 and line[i-1] in " \t":
1217 i = i-1
1218 if i > 0 and line[i-1] == "\n":
1219 i = i-1
1220 while i > 0 and line[i-1] in " \t":
1221 i = i-1
1222 line = line[:i]
1223 more = self.interp.runsource(line)
David Scherer7aced172000-08-15 01:13:23 +00001224
David Scherer7aced172000-08-15 01:13:23 +00001225 def open_stack_viewer(self, event=None):
Chui Tey5d2af632002-05-26 13:36:41 +00001226 if self.interp.rpcclt:
1227 return self.interp.remote_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +00001228 try:
1229 sys.last_traceback
1230 except:
1231 tkMessageBox.showerror("No stack trace",
1232 "There is no stack trace yet.\n"
1233 "(sys.last_traceback is not defined)",
1234 master=self.text)
1235 return
Florent Xiclunad630c042010-04-02 07:24:52 +00001236 from idlelib.StackViewer import StackBrowser
David Scherer7aced172000-08-15 01:13:23 +00001237 sv = StackBrowser(self.root, self.flist)
1238
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001239 def view_restart_mark(self, event=None):
1240 self.text.see("iomark")
1241 self.text.see("restart")
1242
1243 def restart_shell(self, event=None):
Terry Jan Reedyb98000a2012-01-31 02:09:25 -05001244 "Callback for Run/Restart Shell Cntl-F6"
1245 self.interp.restart_subprocess(with_cwd=True)
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001246
David Scherer7aced172000-08-15 01:13:23 +00001247 def showprompt(self):
1248 self.resetoutput()
1249 try:
1250 s = str(sys.ps1)
1251 except:
1252 s = ""
1253 self.console.write(s)
1254 self.text.mark_set("insert", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001255 self.set_line_and_column()
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +00001256 self.io.reset_undo()
David Scherer7aced172000-08-15 01:13:23 +00001257
1258 def resetoutput(self):
1259 source = self.text.get("iomark", "end-1c")
1260 if self.history:
1261 self.history.history_store(source)
1262 if self.text.get("end-2c") != "\n":
1263 self.text.insert("end-1c", "\n")
1264 self.text.mark_set("iomark", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001265 self.set_line_and_column()
David Scherer7aced172000-08-15 01:13:23 +00001266 sys.stdout.softspace = 0
1267
1268 def write(self, s, tags=()):
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001269 try:
1270 self.text.mark_gravity("iomark", "right")
1271 OutputWindow.write(self, s, tags, "iomark")
1272 self.text.mark_gravity("iomark", "left")
1273 except:
1274 pass
David Scherer7aced172000-08-15 01:13:23 +00001275 if self.canceled:
1276 self.canceled = 0
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001277 if not use_subprocess:
1278 raise KeyboardInterrupt
David Scherer7aced172000-08-15 01:13:23 +00001279
Andrew Svetlov5018db72012-11-01 22:39:14 +02001280 def rmenu_check_cut(self):
1281 try:
1282 if self.text.compare('sel.first', '<', 'iomark'):
1283 return 'disabled'
1284 except TclError: # no selection, so the index 'sel.first' doesn't exist
1285 return 'disabled'
1286 return super(PyShell, self).rmenu_check_cut()
1287
1288 def rmenu_check_paste(self):
1289 if self.text.compare('insert', '<', 'iomark'):
1290 return 'disabled'
1291 return super(PyShell, self).rmenu_check_paste()
1292
Serhiy Storchaka9abc8302013-01-25 15:30:35 +02001293class PseudoFile(io.TextIOBase):
David Scherer7aced172000-08-15 01:13:23 +00001294
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001295 def __init__(self, shell, tags, encoding=None):
David Scherer7aced172000-08-15 01:13:23 +00001296 self.shell = shell
1297 self.tags = tags
Chui Tey5d2af632002-05-26 13:36:41 +00001298 self.softspace = 0
Serhiy Storchaka9abc8302013-01-25 15:30:35 +02001299 self._encoding = encoding
David Scherer7aced172000-08-15 01:13:23 +00001300
Serhiy Storchaka9abc8302013-01-25 15:30:35 +02001301 @property
1302 def encoding(self):
1303 return self._encoding
David Scherer7aced172000-08-15 01:13:23 +00001304
Serhiy Storchaka9abc8302013-01-25 15:30:35 +02001305 @property
1306 def name(self):
1307 return '<%s>' % self.tags
David Scherer7aced172000-08-15 01:13:23 +00001308
1309 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001310 return True
David Scherer7aced172000-08-15 01:13:23 +00001311
Serhiy Storchaka9abc8302013-01-25 15:30:35 +02001312
1313class PseudoOutputFile(PseudoFile):
1314
1315 def writable(self):
1316 return True
Martin v. Löwise2b56242012-07-25 10:56:22 +02001317
1318 def write(self, s):
Serhiy Storchaka9abc8302013-01-25 15:30:35 +02001319 if self.closed:
1320 raise ValueError("write to closed file")
1321 if not isinstance(s, (basestring, bytearray)):
1322 raise TypeError('must be string, not ' + type(s).__name__)
1323 return self.shell.write(s, self.tags)
1324
1325
1326class PseudoInputFile(PseudoFile):
1327
1328 def __init__(self, shell, tags, encoding=None):
1329 PseudoFile.__init__(self, shell, tags, encoding)
1330 self._line_buffer = ''
1331
1332 def readable(self):
1333 return True
1334
1335 def read(self, size=-1):
1336 if self.closed:
1337 raise ValueError("read from closed file")
1338 if size is None:
1339 size = -1
1340 elif not isinstance(size, int):
1341 raise TypeError('must be int, not ' + type(size).__name__)
1342 result = self._line_buffer
1343 self._line_buffer = ''
1344 if size < 0:
1345 while True:
1346 line = self.shell.readline()
1347 if not line: break
1348 result += line
1349 else:
1350 while len(result) < size:
1351 line = self.shell.readline()
1352 if not line: break
1353 result += line
1354 self._line_buffer = result[size:]
1355 result = result[:size]
1356 return result
1357
1358 def readline(self, size=-1):
1359 if self.closed:
1360 raise ValueError("read from closed file")
1361 if size is None:
1362 size = -1
1363 elif not isinstance(size, int):
1364 raise TypeError('must be int, not ' + type(size).__name__)
1365 line = self._line_buffer or self.shell.readline()
1366 if size < 0:
1367 size = len(line)
1368 self._line_buffer = line[size:]
1369 return line[:size]
Martin v. Löwise2b56242012-07-25 10:56:22 +02001370
Roger Serwy53dc4f02013-04-11 19:13:21 -05001371 def close(self):
1372 self.shell.close()
1373
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001374
David Scherer7aced172000-08-15 01:13:23 +00001375usage_msg = """\
David Scherer7aced172000-08-15 01:13:23 +00001376
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001377USAGE: idle [-deins] [-t title] [file]*
1378 idle [-dns] [-t title] (-c cmd | -r file) [arg]*
1379 idle [-dns] [-t title] - [arg]*
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001380
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001381 -h print this help message and exit
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001382 -n run IDLE without a subprocess (see Help/IDLE Help for details)
David Scherer7aced172000-08-15 01:13:23 +00001383
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001384The following options will override the IDLE 'settings' configuration:
Kurt B. Kaiser96d88422001-07-17 04:59:01 +00001385
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001386 -e open an edit window
1387 -i open a shell window
1388
1389The following options imply -i and will open a shell:
1390
1391 -c cmd run the command in a shell, or
1392 -r file run script from file
1393
1394 -d enable the debugger
1395 -s run $IDLESTARTUP or $PYTHONSTARTUP before anything else
1396 -t title set title of shell window
1397
1398A default edit window will be bypassed when -c, -r, or - are used.
1399
1400[arg]* are passed to the command (-c) or script (-r) in sys.argv[1:].
1401
1402Examples:
1403
1404idle
1405 Open an edit window or shell depending on IDLE's configuration.
1406
1407idle foo.py foobar.py
1408 Edit the files, also open a shell if configured to start with shell.
1409
1410idle -est "Baz" foo.py
1411 Run $IDLESTARTUP or $PYTHONSTARTUP, edit foo.py, and open a shell
1412 window with the title "Baz".
1413
1414idle -c "import sys; print sys.argv" "foo"
1415 Open a shell window and run the command, passing "-c" in sys.argv[0]
1416 and "foo" in sys.argv[1].
1417
1418idle -d -s -r foo.py "Hello World"
1419 Open a shell window, run a startup script, enable the debugger, and
1420 run foo.py, passing "foo.py" in sys.argv[0] and "Hello World" in
1421 sys.argv[1].
1422
1423echo "import sys; print sys.argv" | idle - "foobar"
1424 Open a shell window, run the script piped in, passing '' in sys.argv[0]
1425 and "foobar" in sys.argv[1].
David Scherer7aced172000-08-15 01:13:23 +00001426"""
1427
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001428def main():
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001429 global flist, root, use_subprocess
David Scherer7aced172000-08-15 01:13:23 +00001430
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001431 use_subprocess = True
Roger Serwy34d0c662013-03-31 23:28:55 -05001432 enable_shell = False
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001433 enable_edit = False
1434 debug = False
1435 cmd = None
1436 script = None
1437 startup = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001438 try:
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001439 opts, args = getopt.getopt(sys.argv[1:], "c:deihnr:st:")
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001440 except getopt.error, msg:
1441 sys.stderr.write("Error: %s\n" % str(msg))
1442 sys.stderr.write(usage_msg)
1443 sys.exit(2)
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001444 for o, a in opts:
1445 if o == '-c':
1446 cmd = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001447 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001448 if o == '-d':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001449 debug = True
1450 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001451 if o == '-e':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001452 enable_edit = True
1453 if o == '-h':
1454 sys.stdout.write(usage_msg)
1455 sys.exit()
1456 if o == '-i':
1457 enable_shell = True
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001458 if o == '-n':
1459 use_subprocess = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001460 if o == '-r':
1461 script = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001462 if os.path.isfile(script):
1463 pass
1464 else:
1465 print "No script file: ", script
1466 sys.exit()
1467 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001468 if o == '-s':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001469 startup = True
1470 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001471 if o == '-t':
1472 PyShell.shell_title = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001473 enable_shell = True
1474 if args and args[0] == '-':
1475 cmd = sys.stdin.read()
1476 enable_shell = True
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001477 # process sys.argv and sys.path:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001478 for i in range(len(sys.path)):
1479 sys.path[i] = os.path.abspath(sys.path[i])
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001480 if args and args[0] == '-':
1481 sys.argv = [''] + args[1:]
1482 elif cmd:
1483 sys.argv = ['-c'] + args
1484 elif script:
1485 sys.argv = [script] + args
1486 elif args:
1487 enable_edit = True
1488 pathx = []
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001489 for filename in args:
1490 pathx.append(os.path.dirname(filename))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001491 for dir in pathx:
1492 dir = os.path.abspath(dir)
Florent Xiclunad630c042010-04-02 07:24:52 +00001493 if dir not in sys.path:
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001494 sys.path.insert(0, dir)
Kurt B. Kaiserff002b92002-12-21 21:39:11 +00001495 else:
1496 dir = os.getcwd()
1497 if not dir in sys.path:
1498 sys.path.insert(0, dir)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001499 # check the IDLE settings configuration (but command line overrides)
1500 edit_start = idleConf.GetOption('main', 'General',
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001501 'editor-on-startup', type='bool')
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001502 enable_edit = enable_edit or edit_start
Roger Serwy34d0c662013-03-31 23:28:55 -05001503 enable_shell = enable_shell or not enable_edit
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001504 # start editor and/or shell windows:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001505 root = Tk(className="Idle")
Ronald Oussoren19302d92006-06-11 14:33:36 +00001506
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001507 fixwordbreaks(root)
1508 root.withdraw()
1509 flist = PyShellFileList(root)
Ronald Oussoren19302d92006-06-11 14:33:36 +00001510 macosxSupport.setupApp(root, flist)
1511
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001512 if enable_edit:
1513 if not (cmd or script):
Andrew Svetlov7c010ee2012-03-21 13:35:08 +02001514 for filename in args[:]:
1515 if flist.open(filename) is None:
1516 # filename is a directory actually, disconsider it
1517 args.remove(filename)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001518 if not args:
1519 flist.new()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001520 if enable_shell:
Ronald Oussoren19302d92006-06-11 14:33:36 +00001521 shell = flist.open_shell()
1522 if not shell:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001523 return # couldn't open shell
Ronald Oussoren19302d92006-06-11 14:33:36 +00001524
1525 if macosxSupport.runningAsOSXApp() and flist.dict:
1526 # On OSX: when the user has double-clicked on a file that causes
Tim Peters4f96f1f2006-06-11 19:42:51 +00001527 # IDLE to be launched the shell window will open just in front of
1528 # the file she wants to see. Lower the interpreter window when
Ronald Oussoren19302d92006-06-11 14:33:36 +00001529 # there are open files.
1530 shell.top.lower()
1531
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001532 shell = flist.pyshell
1533 # handle remaining options:
1534 if debug:
1535 shell.open_debugger()
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001536 if startup:
1537 filename = os.environ.get("IDLESTARTUP") or \
1538 os.environ.get("PYTHONSTARTUP")
1539 if filename and os.path.isfile(filename):
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001540 shell.interp.execfile(filename)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001541 if shell and cmd or script:
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001542 shell.interp.runcommand("""if 1:
1543 import sys as _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001544 _sys.argv = %r
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001545 del _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001546 \n""" % (sys.argv,))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001547 if cmd:
1548 shell.interp.execsource(cmd)
1549 elif script:
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001550 shell.interp.prepend_syspath(script)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001551 shell.interp.execfile(script)
Ronald Oussoren19302d92006-06-11 14:33:36 +00001552
Ned Deily2a6f4b32011-01-30 00:18:47 +00001553 # Check for problematic OS X Tk versions and print a warning message
1554 # in the IDLE shell window; this is less intrusive than always opening
1555 # a separate window.
1556 tkversionwarning = macosxSupport.tkVersionWarning(root)
1557 if tkversionwarning:
1558 shell.interp.runcommand(''.join(("print('", tkversionwarning, "')")))
1559
Terry Jan Reedyeaa7e782012-05-26 20:33:32 -04001560 while flist.inversedict: # keep IDLE running while files are open.
1561 root.mainloop()
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001562 root.destroy()
1563
David Scherer7aced172000-08-15 01:13:23 +00001564if __name__ == "__main__":
Kurt B. Kaiser9e8b8282003-06-15 17:38:45 +00001565 sys.modules['PyShell'] = sys.modules['__main__']
David Scherer7aced172000-08-15 01:13:23 +00001566 main()