blob: 0a77bb585365396b89d0243e0bdf243ee1be69b2 [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
Chui Tey5d2af632002-05-26 13:36:41 +0000373 rpcclt = None
374 rpcpid = None
375
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000376 def spawn_subprocess(self):
Florent Xiclunac8a730b2010-03-25 20:32:07 +0000377 if self.subprocess_arglist is None:
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +0000378 self.subprocess_arglist = self.build_subprocess_arglist()
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000379 args = self.subprocess_arglist
Kurt B. Kaiserb7855182003-08-14 14:54:28 +0000380 self.rpcpid = os.spawnv(os.P_NOWAIT, sys.executable, args)
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000381
Tony Lowndsf53dec22002-12-20 04:24:43 +0000382 def build_subprocess_arglist(self):
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +0000383 assert (self.port!=0), (
384 "Socket should have been assigned a port number.")
Tony Lownds2398d572003-05-13 15:28:21 +0000385 w = ['-W' + s for s in sys.warnoptions]
Georg Brandld0761532006-10-12 07:57:21 +0000386 if 1/2 > 0: # account for new division
387 w.append('-Qnew')
Tony Lownds2398d572003-05-13 15:28:21 +0000388 # Maybe IDLE is installed and is being accessed via sys.path,
389 # or maybe it's not installed and the idle.py script is being
390 # run from the IDLE source directory.
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000391 del_exitf = idleConf.GetOption('main', 'General', 'delete-exitfunc',
392 default=False, type='bool')
Tony Lownds2398d572003-05-13 15:28:21 +0000393 if __name__ == 'idlelib.PyShell':
Walter Dörwald70a6b492004-02-12 17:35:32 +0000394 command = "__import__('idlelib.run').run.main(%r)" % (del_exitf,)
Tony Lowndsf2324b92002-09-29 00:34:10 +0000395 else:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000396 command = "__import__('run').main(%r)" % (del_exitf,)
Kurt B. Kaiserb7855182003-08-14 14:54:28 +0000397 if sys.platform[:3] == 'win' and ' ' in sys.executable:
398 # handle embedded space in path by quoting the argument
399 decorated_exec = '"%s"' % sys.executable
400 else:
401 decorated_exec = sys.executable
402 return [decorated_exec] + w + ["-c", command, str(self.port)]
Tony Lowndsf2324b92002-09-29 00:34:10 +0000403
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000404 def start_subprocess(self):
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +0000405 addr = (HOST, self.port)
406 # GUI makes several attempts to acquire socket, listens for connection
Kurt B. Kaiser5db48432003-05-15 03:40:51 +0000407 for i in range(3):
Chui Tey5d2af632002-05-26 13:36:41 +0000408 time.sleep(i)
409 try:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000410 self.rpcclt = MyRPCClient(addr)
Chui Tey5d2af632002-05-26 13:36:41 +0000411 break
412 except socket.error, err:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000413 pass
Chui Tey5d2af632002-05-26 13:36:41 +0000414 else:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000415 self.display_port_binding_error()
416 return None
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +0000417 # if PORT was 0, system will assign an 'ephemeral' port. Find it out:
418 self.port = self.rpcclt.listening_sock.getsockname()[1]
419 # if PORT was not 0, probably working with a remote execution server
420 if PORT != 0:
421 # To allow reconnection within the 2MSL wait (cf. Stevens TCP
422 # V1, 18.6), set SO_REUSEADDR. Note that this can be problematic
423 # on Windows since the implementation allows two active sockets on
424 # the same address!
425 self.rpcclt.listening_sock.setsockopt(socket.SOL_SOCKET,
426 socket.SO_REUSEADDR, 1)
427 self.spawn_subprocess()
428 #time.sleep(20) # test to simulate GUI not accepting connection
Kurt B. Kaiserb4179362002-07-26 00:06:42 +0000429 # Accept the connection from the Python execution server
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000430 self.rpcclt.listening_sock.settimeout(10)
431 try:
432 self.rpcclt.accept()
433 except socket.timeout, err:
434 self.display_no_subprocess_error()
435 return None
Serhiy Storchaka9abc8302013-01-25 15:30:35 +0200436 self.rpcclt.register("console", self.tkconsole)
437 self.rpcclt.register("stdin", self.tkconsole.stdin)
Kurt B. Kaiser969de452002-06-12 03:28:57 +0000438 self.rpcclt.register("stdout", self.tkconsole.stdout)
439 self.rpcclt.register("stderr", self.tkconsole.stderr)
Chui Tey5d2af632002-05-26 13:36:41 +0000440 self.rpcclt.register("flist", self.tkconsole.flist)
Kurt B. Kaiser8cd0def2003-01-31 05:06:43 +0000441 self.rpcclt.register("linecache", linecache)
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000442 self.rpcclt.register("interp", self)
Terry Jan Reedyb98000a2012-01-31 02:09:25 -0500443 self.transfer_path(with_cwd=True)
Chui Tey5d2af632002-05-26 13:36:41 +0000444 self.poll_subprocess()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000445 return self.rpcclt
Chui Tey5d2af632002-05-26 13:36:41 +0000446
Terry Jan Reedyb98000a2012-01-31 02:09:25 -0500447 def restart_subprocess(self, with_cwd=False):
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000448 if self.restarting:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000449 return self.rpcclt
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000450 self.restarting = True
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000451 # close only the subprocess debugger
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000452 debug = self.getdebugger()
453 if debug:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000454 try:
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000455 # Only close subprocess debugger, don't unregister gui_adap!
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000456 RemoteDebugger.close_subprocess_debugger(self.rpcclt)
457 except:
458 pass
459 # Kill subprocess, spawn a new one, accept connection.
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000460 self.rpcclt.close()
461 self.unix_terminate()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000462 console = self.tkconsole
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000463 was_executing = console.executing
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000464 console.executing = False
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000465 self.spawn_subprocess()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000466 try:
467 self.rpcclt.accept()
468 except socket.timeout, err:
469 self.display_no_subprocess_error()
470 return None
Terry Jan Reedyb98000a2012-01-31 02:09:25 -0500471 self.transfer_path(with_cwd=with_cwd)
Roger Serwyad8cad32013-04-03 00:42:24 -0500472 console.stop_readline()
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000473 # annotate restart in shell window and mark it
Kurt B. Kaiser4cc5ef52003-01-22 00:23:23 +0000474 console.text.delete("iomark", "end-1c")
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000475 if was_executing:
476 console.write('\n')
477 console.showprompt()
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000478 halfbar = ((int(console.width) - 16) // 2) * '='
479 console.write(halfbar + ' RESTART ' + halfbar)
480 console.text.mark_set("restart", "end-1c")
481 console.text.mark_gravity("restart", "left")
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000482 console.showprompt()
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000483 # restart subprocess debugger
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000484 if debug:
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000485 # Restarted debugger connects to current instance of debug GUI
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000486 gui = RemoteDebugger.restart_subprocess_debugger(self.rpcclt)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000487 # reload remote debugger breakpoints for all PyShellEditWindows
488 debug.load_breakpoints()
Ned Deily86d669b2011-10-30 19:58:04 -0700489 self.compile.compiler.flags = self.original_compiler_flags
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000490 self.restarting = False
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000491 return self.rpcclt
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000492
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000493 def __request_interrupt(self):
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000494 self.rpcclt.remotecall("exec", "interrupt_the_server", (), {})
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000495
496 def interrupt_subprocess(self):
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000497 threading.Thread(target=self.__request_interrupt).start()
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000498
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000499 def kill_subprocess(self):
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000500 try:
501 self.rpcclt.close()
502 except AttributeError: # no socket
503 pass
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000504 self.unix_terminate()
505 self.tkconsole.executing = False
506 self.rpcclt = None
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000507
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000508 def unix_terminate(self):
509 "UNIX: make sure subprocess is terminated and collect status"
510 if hasattr(os, 'kill'):
511 try:
512 os.kill(self.rpcpid, SIGTERM)
513 except OSError:
514 # process already terminated:
515 return
516 else:
517 try:
518 os.waitpid(self.rpcpid, 0)
519 except OSError:
520 return
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000521
Terry Jan Reedyb98000a2012-01-31 02:09:25 -0500522 def transfer_path(self, with_cwd=False):
523 if with_cwd: # Issue 13506
524 path = [''] # include Current Working Directory
525 path.extend(sys.path)
526 else:
527 path = sys.path
Terry Jan Reedy1d4ae482012-01-31 02:55:32 -0500528
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000529 self.runcommand("""if 1:
530 import sys as _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +0000531 _sys.path = %r
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000532 del _sys
Terry Jan Reedyb98000a2012-01-31 02:09:25 -0500533 \n""" % (path,))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000534
Chui Tey5d2af632002-05-26 13:36:41 +0000535 active_seq = None
536
537 def poll_subprocess(self):
538 clt = self.rpcclt
539 if clt is None:
540 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000541 try:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000542 response = clt.pollresponse(self.active_seq, wait=0.05)
543 except (EOFError, IOError, KeyboardInterrupt):
544 # lost connection or subprocess terminated itself, restart
545 # [the KBI is from rpc.SocketIO.handle_EOF()]
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000546 if self.tkconsole.closing:
547 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000548 response = None
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000549 self.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000550 if response:
551 self.tkconsole.resetoutput()
552 self.active_seq = None
553 how, what = response
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000554 console = self.tkconsole.console
Chui Tey5d2af632002-05-26 13:36:41 +0000555 if how == "OK":
556 if what is not None:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000557 print >>console, repr(what)
Chui Tey5d2af632002-05-26 13:36:41 +0000558 elif how == "EXCEPTION":
Chui Tey5d2af632002-05-26 13:36:41 +0000559 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
560 self.remote_stack_viewer()
561 elif how == "ERROR":
Kurt B. Kaiser0930c432002-12-06 21:45:24 +0000562 errmsg = "PyShell.ModifiedInterpreter: Subprocess ERROR:\n"
563 print >>sys.__stderr__, errmsg, what
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000564 print >>console, errmsg, what
565 # we received a response to the currently active seq number:
Kurt B. Kaiserd112bc72006-08-16 05:01:42 +0000566 try:
567 self.tkconsole.endexecuting()
568 except AttributeError: # shell may have closed
569 pass
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000570 # Reschedule myself
571 if not self.tkconsole.closing:
572 self.tkconsole.text.after(self.tkconsole.pollinterval,
573 self.poll_subprocess)
Chui Tey5d2af632002-05-26 13:36:41 +0000574
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000575 debugger = None
576
577 def setdebugger(self, debugger):
578 self.debugger = debugger
579
580 def getdebugger(self):
581 return self.debugger
582
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000583 def open_remote_stack_viewer(self):
584 """Initiate the remote stack viewer from a separate thread.
585
586 This method is called from the subprocess, and by returning from this
587 method we allow the subprocess to unblock. After a bit the shell
588 requests the subprocess to open the remote stack viewer which returns a
Ezio Melottic569cfe2010-07-23 16:55:21 +0000589 static object looking at the last exception. It is queried through
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000590 the RPC mechanism.
591
592 """
593 self.tkconsole.text.after(300, self.remote_stack_viewer)
594 return
595
Chui Tey5d2af632002-05-26 13:36:41 +0000596 def remote_stack_viewer(self):
Florent Xiclunad630c042010-04-02 07:24:52 +0000597 from idlelib import RemoteObjectBrowser
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000598 oid = self.rpcclt.remotequeue("exec", "stackviewer", ("flist",), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000599 if oid is None:
600 self.tkconsole.root.bell()
601 return
602 item = RemoteObjectBrowser.StubObjectTreeItem(self.rpcclt, oid)
Florent Xiclunad630c042010-04-02 07:24:52 +0000603 from idlelib.TreeWidget import ScrolledCanvas, TreeNode
Chui Tey5d2af632002-05-26 13:36:41 +0000604 top = Toplevel(self.tkconsole.root)
Kurt B. Kaiser73360a32004-03-08 18:15:31 +0000605 theme = idleConf.GetOption('main','Theme','name')
606 background = idleConf.GetHighlight(theme, 'normal')['background']
607 sc = ScrolledCanvas(top, bg=background, highlightthickness=0)
Chui Tey5d2af632002-05-26 13:36:41 +0000608 sc.frame.pack(expand=1, fill="both")
609 node = TreeNode(sc.canvas, None, item)
610 node.expand()
611 # XXX Should GC the remote tree when closing the window
612
David Scherer7aced172000-08-15 01:13:23 +0000613 gid = 0
614
615 def execsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000616 "Like runsource() but assumes complete exec source"
David Scherer7aced172000-08-15 01:13:23 +0000617 filename = self.stuffsource(source)
618 self.execfile(filename, source)
619
620 def execfile(self, filename, source=None):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000621 "Execute an existing file"
David Scherer7aced172000-08-15 01:13:23 +0000622 if source is None:
623 source = open(filename, "r").read()
624 try:
625 code = compile(source, filename, "exec")
626 except (OverflowError, SyntaxError):
627 self.tkconsole.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000628 tkerr = self.tkconsole.stderr
629 print>>tkerr, '*** Error in script or command!\n'
630 print>>tkerr, 'Traceback (most recent call last):'
David Scherer7aced172000-08-15 01:13:23 +0000631 InteractiveInterpreter.showsyntaxerror(self, filename)
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000632 self.tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000633 else:
634 self.runcode(code)
635
636 def runsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000637 "Extend base class method: Stuff the source in the line cache first"
David Scherer7aced172000-08-15 01:13:23 +0000638 filename = self.stuffsource(source)
639 self.more = 0
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000640 self.save_warnings_filters = warnings.filters[:]
641 warnings.filterwarnings(action="error", category=SyntaxWarning)
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000642 if isinstance(source, types.UnicodeType):
Florent Xiclunad630c042010-04-02 07:24:52 +0000643 from idlelib import IOBinding
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000644 try:
645 source = source.encode(IOBinding.encoding)
646 except UnicodeError:
647 self.tkconsole.resetoutput()
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +0000648 self.write("Unsupported characters in input\n")
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000649 return
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000650 try:
Kurt B. Kaiser935ea9a2005-05-10 03:44:24 +0000651 # InteractiveInterpreter.runsource() calls its runcode() method,
652 # which is overridden (see below)
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000653 return InteractiveInterpreter.runsource(self, source, filename)
654 finally:
655 if self.save_warnings_filters is not None:
656 warnings.filters[:] = self.save_warnings_filters
657 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000658
659 def stuffsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000660 "Stuff source in the filename cache"
David Scherer7aced172000-08-15 01:13:23 +0000661 filename = "<pyshell#%d>" % self.gid
662 self.gid = self.gid + 1
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000663 lines = source.split("\n")
David Scherer7aced172000-08-15 01:13:23 +0000664 linecache.cache[filename] = len(source)+1, 0, lines, filename
665 return filename
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000666
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000667 def prepend_syspath(self, filename):
668 "Prepend sys.path with file's directory if not already included"
669 self.runcommand("""if 1:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000670 _filename = %r
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000671 import sys as _sys
672 from os.path import dirname as _dirname
673 _dir = _dirname(_filename)
674 if not _dir in _sys.path:
675 _sys.path.insert(0, _dir)
676 del _filename, _sys, _dirname, _dir
Walter Dörwald70a6b492004-02-12 17:35:32 +0000677 \n""" % (filename,))
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000678
David Scherer7aced172000-08-15 01:13:23 +0000679 def showsyntaxerror(self, filename=None):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000680 """Extend base class method: Add Colorizing
681
682 Color the offending position instead of printing it and pointing at it
683 with a caret.
684
685 """
David Scherer7aced172000-08-15 01:13:23 +0000686 text = self.tkconsole.text
687 stuff = self.unpackerror()
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000688 if stuff:
689 msg, lineno, offset, line = stuff
690 if lineno == 1:
691 pos = "iomark + %d chars" % (offset-1)
692 else:
693 pos = "iomark linestart + %d lines + %d chars" % \
694 (lineno-1, offset-1)
695 text.tag_add("ERROR", pos)
696 text.see(pos)
697 char = text.get(pos)
698 if char and char in IDENTCHARS:
699 text.tag_add("ERROR", pos + " wordstart", pos)
700 self.tkconsole.resetoutput()
701 self.write("SyntaxError: %s\n" % str(msg))
702 else:
David Scherer7aced172000-08-15 01:13:23 +0000703 self.tkconsole.resetoutput()
704 InteractiveInterpreter.showsyntaxerror(self, filename)
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000705 self.tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000706
707 def unpackerror(self):
708 type, value, tb = sys.exc_info()
709 ok = type is SyntaxError
710 if ok:
711 try:
712 msg, (dummy_filename, lineno, offset, line) = value
Kurt B. Kaiserbea57c62003-07-09 04:27:24 +0000713 if not offset:
714 offset = 0
David Scherer7aced172000-08-15 01:13:23 +0000715 except:
716 ok = 0
717 if ok:
718 return msg, lineno, offset, line
719 else:
720 return None
721
722 def showtraceback(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000723 "Extend base class method to reset output properly"
David Scherer7aced172000-08-15 01:13:23 +0000724 self.tkconsole.resetoutput()
725 self.checklinecache()
726 InteractiveInterpreter.showtraceback(self)
Chui Tey5d2af632002-05-26 13:36:41 +0000727 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
728 self.tkconsole.open_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +0000729
730 def checklinecache(self):
731 c = linecache.cache
732 for key in c.keys():
733 if key[:1] + key[-1:] != "<>":
734 del c[key]
735
Chui Tey5d2af632002-05-26 13:36:41 +0000736 def runcommand(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000737 "Run the code without invoking the debugger"
Chui Tey5d2af632002-05-26 13:36:41 +0000738 # The code better not raise an exception!
739 if self.tkconsole.executing:
Neal Norwitzf4c4f112002-11-30 18:49:10 +0000740 self.display_executing_dialog()
Chui Tey5d2af632002-05-26 13:36:41 +0000741 return 0
742 if self.rpcclt:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000743 self.rpcclt.remotequeue("exec", "runcode", (code,), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000744 else:
745 exec code in self.locals
746 return 1
747
David Scherer7aced172000-08-15 01:13:23 +0000748 def runcode(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000749 "Override base class method"
Chui Tey5d2af632002-05-26 13:36:41 +0000750 if self.tkconsole.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000751 self.interp.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000752 self.checklinecache()
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000753 if self.save_warnings_filters is not None:
754 warnings.filters[:] = self.save_warnings_filters
755 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000756 debugger = self.debugger
757 try:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000758 self.tkconsole.beginexecuting()
Kurt B. Kaiserdddeb0e2007-02-06 03:21:40 +0000759 if not debugger and self.rpcclt is not None:
760 self.active_seq = self.rpcclt.asyncqueue("exec", "runcode",
761 (code,), {})
762 elif debugger:
763 debugger.run(code, self.locals)
764 else:
765 exec code in self.locals
766 except SystemExit:
767 if not self.tkconsole.closing:
768 if tkMessageBox.askyesno(
769 "Exit?",
770 "Do you want to exit altogether?",
771 default="yes",
772 master=self.tkconsole.text):
Kurt B. Kaiserf137e1d2006-08-16 07:04:17 +0000773 raise
Kurt B. Kaiserdddeb0e2007-02-06 03:21:40 +0000774 else:
775 self.showtraceback()
776 else:
777 raise
778 except:
779 if use_subprocess:
780 print >>self.tkconsole.stderr, \
781 "IDLE internal error in runcode()"
David Scherer7aced172000-08-15 01:13:23 +0000782 self.showtraceback()
Kurt B. Kaiserdddeb0e2007-02-06 03:21:40 +0000783 self.tkconsole.endexecuting()
784 else:
785 if self.tkconsole.canceled:
786 self.tkconsole.canceled = False
787 print >>self.tkconsole.stderr, "KeyboardInterrupt"
788 else:
789 self.showtraceback()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000790 finally:
791 if not use_subprocess:
Kurt B. Kaiserd112bc72006-08-16 05:01:42 +0000792 try:
793 self.tkconsole.endexecuting()
794 except AttributeError: # shell may have closed
795 pass
David Scherer7aced172000-08-15 01:13:23 +0000796
797 def write(self, s):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000798 "Override base class method"
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000799 self.tkconsole.stderr.write(s)
David Scherer7aced172000-08-15 01:13:23 +0000800
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000801 def display_port_binding_error(self):
802 tkMessageBox.showerror(
803 "Port Binding Error",
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +0000804 "IDLE can't bind to a TCP/IP port, which is necessary to "
805 "communicate with its Python execution server. This might be "
806 "because no networking is installed on this computer. "
807 "Run IDLE with the -n command line switch to start without a "
808 "subprocess and refer to Help/IDLE Help 'Running without a "
809 "subprocess' for further details.",
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000810 master=self.tkconsole.text)
811
812 def display_no_subprocess_error(self):
813 tkMessageBox.showerror(
814 "Subprocess Startup Error",
815 "IDLE's subprocess didn't make connection. Either IDLE can't "
816 "start a subprocess or personal firewall software is blocking "
817 "the connection.",
818 master=self.tkconsole.text)
819
820 def display_executing_dialog(self):
821 tkMessageBox.showerror(
822 "Already executing",
823 "The Python Shell window is already executing a command; "
824 "please wait until it is finished.",
825 master=self.tkconsole.text)
826
827
David Scherer7aced172000-08-15 01:13:23 +0000828class PyShell(OutputWindow):
829
Terry Jan Reedyd676a3a2013-03-30 18:50:43 -0400830 shell_title = "Python " + python_version() + " Shell"
David Scherer7aced172000-08-15 01:13:23 +0000831
832 # Override classes
833 ColorDelegator = ModifiedColorDelegator
834 UndoDelegator = ModifiedUndoDelegator
835
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000836 # Override menus
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000837 menu_specs = [
838 ("file", "_File"),
839 ("edit", "_Edit"),
Kurt B. Kaiser4cc5ef52003-01-22 00:23:23 +0000840 ("debug", "_Debug"),
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000841 ("options", "_Options"),
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000842 ("windows", "_Windows"),
843 ("help", "_Help"),
844 ]
David Scherer7aced172000-08-15 01:13:23 +0000845
Ronald Oussoren19302d92006-06-11 14:33:36 +0000846 if macosxSupport.runningAsOSXApp():
Ronald Oussoren19302d92006-06-11 14:33:36 +0000847 menu_specs[-2] = ("windows", "_Window")
848
849
David Scherer7aced172000-08-15 01:13:23 +0000850 # New classes
Florent Xiclunad630c042010-04-02 07:24:52 +0000851 from idlelib.IdleHistory import History
David Scherer7aced172000-08-15 01:13:23 +0000852
853 def __init__(self, flist=None):
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000854 if use_subprocess:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000855 ms = self.menu_specs
856 if ms[2][0] != "shell":
Kurt B. Kaiser7ae35482006-08-16 21:45:59 +0000857 ms.insert(2, ("shell", "She_ll"))
David Scherer7aced172000-08-15 01:13:23 +0000858 self.interp = ModifiedInterpreter(self)
859 if flist is None:
860 root = Tk()
861 fixwordbreaks(root)
862 root.withdraw()
863 flist = PyShellFileList(root)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000864 #
David Scherer7aced172000-08-15 01:13:23 +0000865 OutputWindow.__init__(self, flist, None, None)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000866 #
Kurt B. Kaiser6af44982005-01-19 00:22:59 +0000867## self.config(usetabs=1, indentwidth=8, context_use_ps1=1)
868 self.usetabs = True
869 # indentwidth must be 8 when using tabs. See note in EditorWindow:
870 self.indentwidth = 8
871 self.context_use_ps1 = True
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000872 #
David Scherer7aced172000-08-15 01:13:23 +0000873 text = self.text
874 text.configure(wrap="char")
875 text.bind("<<newline-and-indent>>", self.enter_callback)
876 text.bind("<<plain-newline-and-indent>>", self.linefeed_callback)
877 text.bind("<<interrupt-execution>>", self.cancel_callback)
David Scherer7aced172000-08-15 01:13:23 +0000878 text.bind("<<end-of-file>>", self.eof_callback)
879 text.bind("<<open-stack-viewer>>", self.open_stack_viewer)
Kurt B. Kaiser57bfe5d2003-05-10 00:09:52 +0000880 text.bind("<<toggle-debugger>>", self.toggle_debugger)
David Scherer7aced172000-08-15 01:13:23 +0000881 text.bind("<<toggle-jit-stack-viewer>>", self.toggle_jit_stack_viewer)
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000882 if use_subprocess:
883 text.bind("<<view-restart>>", self.view_restart_mark)
884 text.bind("<<restart-shell>>", self.restart_shell)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000885 #
David Scherer7aced172000-08-15 01:13:23 +0000886 self.save_stdout = sys.stdout
887 self.save_stderr = sys.stderr
888 self.save_stdin = sys.stdin
Florent Xiclunad630c042010-04-02 07:24:52 +0000889 from idlelib import IOBinding
Serhiy Storchaka9abc8302013-01-25 15:30:35 +0200890 self.stdin = PseudoInputFile(self, "stdin", IOBinding.encoding)
891 self.stdout = PseudoOutputFile(self, "stdout", IOBinding.encoding)
892 self.stderr = PseudoOutputFile(self, "stderr", IOBinding.encoding)
893 self.console = PseudoOutputFile(self, "console", IOBinding.encoding)
Chui Tey5d2af632002-05-26 13:36:41 +0000894 if not use_subprocess:
895 sys.stdout = self.stdout
896 sys.stderr = self.stderr
Martin v. Löwise2b56242012-07-25 10:56:22 +0200897 sys.stdin = self.stdin
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000898 #
David Scherer7aced172000-08-15 01:13:23 +0000899 self.history = self.History(self.text)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000900 #
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000901 self.pollinterval = 50 # millisec
Chui Tey5d2af632002-05-26 13:36:41 +0000902
Kurt B. Kaiser4d5bc602004-06-06 01:29:22 +0000903 def get_standard_extension_names(self):
904 return idleConf.GetExtensions(shell_only=True)
905
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000906 reading = False
907 executing = False
908 canceled = False
909 endoffile = False
910 closing = False
Roger Serwyad8cad32013-04-03 00:42:24 -0500911 _stop_readline_flag = False
David Scherer7aced172000-08-15 01:13:23 +0000912
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +0000913 def set_warning_stream(self, stream):
Skip Montanarod9161422004-07-06 21:53:27 +0000914 global warning_stream
915 warning_stream = stream
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +0000916
917 def get_warning_stream(self):
918 return warning_stream
919
David Scherer7aced172000-08-15 01:13:23 +0000920 def toggle_debugger(self, event=None):
921 if self.executing:
922 tkMessageBox.showerror("Don't debug now",
923 "You can only toggle the debugger when idle",
924 master=self.text)
925 self.set_debugger_indicator()
926 return "break"
927 else:
928 db = self.interp.getdebugger()
929 if db:
930 self.close_debugger()
931 else:
932 self.open_debugger()
933
934 def set_debugger_indicator(self):
935 db = self.interp.getdebugger()
936 self.setvar("<<toggle-debugger>>", not not db)
937
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000938 def toggle_jit_stack_viewer(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +0000939 pass # All we need is the variable
940
941 def close_debugger(self):
942 db = self.interp.getdebugger()
943 if db:
944 self.interp.setdebugger(None)
945 db.close()
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000946 if self.interp.rpcclt:
947 RemoteDebugger.close_remote_debugger(self.interp.rpcclt)
David Scherer7aced172000-08-15 01:13:23 +0000948 self.resetoutput()
949 self.console.write("[DEBUG OFF]\n")
950 sys.ps1 = ">>> "
951 self.showprompt()
952 self.set_debugger_indicator()
953
954 def open_debugger(self):
Chui Tey5d2af632002-05-26 13:36:41 +0000955 if self.interp.rpcclt:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000956 dbg_gui = RemoteDebugger.start_remote_debugger(self.interp.rpcclt,
957 self)
958 else:
959 dbg_gui = Debugger.Debugger(self)
960 self.interp.setdebugger(dbg_gui)
961 dbg_gui.load_breakpoints()
Chui Tey5d2af632002-05-26 13:36:41 +0000962 sys.ps1 = "[DEBUG ON]\n>>> "
963 self.showprompt()
964 self.set_debugger_indicator()
965
David Scherer7aced172000-08-15 01:13:23 +0000966 def beginexecuting(self):
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000967 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +0000968 self.resetoutput()
969 self.executing = 1
David Scherer7aced172000-08-15 01:13:23 +0000970
971 def endexecuting(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000972 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +0000973 self.executing = 0
974 self.canceled = 0
Chui Tey5d2af632002-05-26 13:36:41 +0000975 self.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000976
977 def close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000978 "Extend EditorWindow.close()"
David Scherer7aced172000-08-15 01:13:23 +0000979 if self.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000980 response = tkMessageBox.askokcancel(
David Scherer7aced172000-08-15 01:13:23 +0000981 "Kill?",
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000982 "The program is still running!\n Do you want to kill it?",
David Scherer7aced172000-08-15 01:13:23 +0000983 default="ok",
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000984 parent=self.text)
Benjamin Peterson5b63acd2008-03-29 15:24:25 +0000985 if response is False:
David Scherer7aced172000-08-15 01:13:23 +0000986 return "cancel"
Roger Serwyad8cad32013-04-03 00:42:24 -0500987 self.stop_readline()
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +0000988 self.canceled = True
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000989 self.closing = True
990 # Wait for poll_subprocess() rescheduling to stop
991 self.text.after(2 * self.pollinterval, self.close2)
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000992
993 def close2(self):
994 return EditorWindow.close(self)
David Scherer7aced172000-08-15 01:13:23 +0000995
996 def _close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000997 "Extend EditorWindow._close(), shut down debugger and execution server"
David Scherer7aced172000-08-15 01:13:23 +0000998 self.close_debugger()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000999 if use_subprocess:
1000 self.interp.kill_subprocess()
David Scherer7aced172000-08-15 01:13:23 +00001001 # Restore std streams
1002 sys.stdout = self.save_stdout
1003 sys.stderr = self.save_stderr
1004 sys.stdin = self.save_stdin
1005 # Break cycles
1006 self.interp = None
1007 self.console = None
David Scherer7aced172000-08-15 01:13:23 +00001008 self.flist.pyshell = None
1009 self.history = None
Kurt B. Kaiser83118c62002-06-24 17:03:37 +00001010 EditorWindow._close(self)
David Scherer7aced172000-08-15 01:13:23 +00001011
1012 def ispythonsource(self, filename):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +00001013 "Override EditorWindow method: never remove the colorizer"
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001014 return True
David Scherer7aced172000-08-15 01:13:23 +00001015
1016 def short_title(self):
1017 return self.shell_title
1018
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +00001019 COPYRIGHT = \
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001020 'Type "copyright", "credits" or "license()" for more information.'
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +00001021
David Scherer7aced172000-08-15 01:13:23 +00001022 def begin(self):
1023 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001024 if use_subprocess:
1025 nosub = ''
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001026 client = self.interp.start_subprocess()
1027 if not client:
1028 self.close()
Kurt B. Kaiser76637292004-01-21 22:10:01 +00001029 return False
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001030 else:
1031 nosub = "==== No Subprocess ===="
Raymond Hettingerbf3f69e2009-01-26 23:29:09 +00001032 self.write("Python %s on %s\n%s\n%s" %
1033 (sys.version, sys.platform, self.COPYRIGHT, nosub))
David Scherer7aced172000-08-15 01:13:23 +00001034 self.showprompt()
Georg Brandl6634bf22008-05-20 07:13:37 +00001035 import Tkinter
1036 Tkinter._default_root = None # 03Jan04 KBK What's this?
Kurt B. Kaiser76637292004-01-21 22:10:01 +00001037 return True
David Scherer7aced172000-08-15 01:13:23 +00001038
Roger Serwyad8cad32013-04-03 00:42:24 -05001039 def stop_readline(self):
1040 if not self.reading: # no nested mainloop to exit.
1041 return
1042 self._stop_readline_flag = True
1043 self.top.quit()
1044
David Scherer7aced172000-08-15 01:13:23 +00001045 def readline(self):
1046 save = self.reading
1047 try:
1048 self.reading = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001049 self.top.mainloop() # nested mainloop()
David Scherer7aced172000-08-15 01:13:23 +00001050 finally:
1051 self.reading = save
Roger Serwyad8cad32013-04-03 00:42:24 -05001052 if self._stop_readline_flag:
1053 self._stop_readline_flag = False
1054 return ""
David Scherer7aced172000-08-15 01:13:23 +00001055 line = self.text.get("iomark", "end-1c")
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001056 if len(line) == 0: # may be EOF if we quit our mainloop with Ctrl-C
1057 line = "\n"
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001058 if isinstance(line, unicode):
Florent Xiclunad630c042010-04-02 07:24:52 +00001059 from idlelib import IOBinding
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001060 try:
1061 line = line.encode(IOBinding.encoding)
1062 except UnicodeError:
1063 pass
David Scherer7aced172000-08-15 01:13:23 +00001064 self.resetoutput()
1065 if self.canceled:
1066 self.canceled = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001067 if not use_subprocess:
1068 raise KeyboardInterrupt
David Scherer7aced172000-08-15 01:13:23 +00001069 if self.endoffile:
1070 self.endoffile = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001071 line = ""
David Scherer7aced172000-08-15 01:13:23 +00001072 return line
1073
1074 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001075 return True
David Scherer7aced172000-08-15 01:13:23 +00001076
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001077 def cancel_callback(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +00001078 try:
1079 if self.text.compare("sel.first", "!=", "sel.last"):
1080 return # Active selection -- always use default binding
1081 except:
1082 pass
1083 if not (self.executing or self.reading):
1084 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001085 self.interp.write("KeyboardInterrupt\n")
David Scherer7aced172000-08-15 01:13:23 +00001086 self.showprompt()
1087 return "break"
1088 self.endoffile = 0
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001089 self.canceled = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001090 if (self.executing and self.interp.rpcclt):
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +00001091 if self.interp.getdebugger():
1092 self.interp.restart_subprocess()
1093 else:
1094 self.interp.interrupt_subprocess()
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001095 if self.reading:
1096 self.top.quit() # exit the nested mainloop() in readline()
David Scherer7aced172000-08-15 01:13:23 +00001097 return "break"
1098
1099 def eof_callback(self, event):
1100 if self.executing and not self.reading:
1101 return # Let the default binding (delete next char) take over
1102 if not (self.text.compare("iomark", "==", "insert") and
1103 self.text.compare("insert", "==", "end-1c")):
1104 return # Let the default binding (delete next char) take over
1105 if not self.executing:
David Scherer7aced172000-08-15 01:13:23 +00001106 self.resetoutput()
1107 self.close()
1108 else:
1109 self.canceled = 0
1110 self.endoffile = 1
1111 self.top.quit()
1112 return "break"
1113
David Scherer7aced172000-08-15 01:13:23 +00001114 def linefeed_callback(self, event):
1115 # Insert a linefeed without entering anything (still autoindented)
1116 if self.reading:
1117 self.text.insert("insert", "\n")
1118 self.text.see("insert")
1119 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001120 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001121 return "break"
1122
1123 def enter_callback(self, event):
1124 if self.executing and not self.reading:
1125 return # Let the default binding (insert '\n') take over
1126 # If some text is selected, recall the selection
1127 # (but only if this before the I/O mark)
1128 try:
1129 sel = self.text.get("sel.first", "sel.last")
1130 if sel:
1131 if self.text.compare("sel.last", "<=", "iomark"):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001132 self.recall(sel, event)
David Scherer7aced172000-08-15 01:13:23 +00001133 return "break"
1134 except:
1135 pass
1136 # If we're strictly before the line containing iomark, recall
1137 # the current line, less a leading prompt, less leading or
1138 # trailing whitespace
1139 if self.text.compare("insert", "<", "iomark linestart"):
1140 # Check if there's a relevant stdin range -- if so, use it
1141 prev = self.text.tag_prevrange("stdin", "insert")
1142 if prev and self.text.compare("insert", "<", prev[1]):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001143 self.recall(self.text.get(prev[0], prev[1]), event)
David Scherer7aced172000-08-15 01:13:23 +00001144 return "break"
1145 next = self.text.tag_nextrange("stdin", "insert")
1146 if next and self.text.compare("insert lineend", ">=", next[0]):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001147 self.recall(self.text.get(next[0], next[1]), event)
David Scherer7aced172000-08-15 01:13:23 +00001148 return "break"
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001149 # No stdin mark -- just get the current line, less any prompt
Kurt B. Kaiserb1754452005-11-18 22:05:48 +00001150 indices = self.text.tag_nextrange("console", "insert linestart")
1151 if indices and \
1152 self.text.compare(indices[0], "<=", "insert linestart"):
1153 self.recall(self.text.get(indices[1], "insert lineend"), event)
1154 else:
1155 self.recall(self.text.get("insert linestart", "insert lineend"), event)
David Scherer7aced172000-08-15 01:13:23 +00001156 return "break"
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001157 # If we're between the beginning of the line and the iomark, i.e.
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001158 # in the prompt area, move to the end of the prompt
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001159 if self.text.compare("insert", "<", "iomark"):
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001160 self.text.mark_set("insert", "iomark")
David Scherer7aced172000-08-15 01:13:23 +00001161 # If we're in the current input and there's only whitespace
1162 # beyond the cursor, erase that whitespace first
1163 s = self.text.get("insert", "end-1c")
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001164 if s and not s.strip():
David Scherer7aced172000-08-15 01:13:23 +00001165 self.text.delete("insert", "end-1c")
1166 # If we're in the current input before its last line,
1167 # insert a newline right at the insert point
1168 if self.text.compare("insert", "<", "end-1c linestart"):
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001169 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001170 return "break"
1171 # We're in the last line; append a newline and submit it
1172 self.text.mark_set("insert", "end-1c")
1173 if self.reading:
1174 self.text.insert("insert", "\n")
1175 self.text.see("insert")
1176 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001177 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001178 self.text.tag_add("stdin", "iomark", "end-1c")
1179 self.text.update_idletasks()
1180 if self.reading:
1181 self.top.quit() # Break out of recursive mainloop() in raw_input()
1182 else:
1183 self.runit()
1184 return "break"
1185
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001186 def recall(self, s, event):
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001187 # remove leading and trailing empty or whitespace lines
1188 s = re.sub(r'^\s*\n', '' , s)
1189 s = re.sub(r'\n\s*$', '', s)
1190 lines = s.split('\n')
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001191 self.text.undo_block_start()
1192 try:
1193 self.text.tag_remove("sel", "1.0", "end")
1194 self.text.mark_set("insert", "end-1c")
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001195 prefix = self.text.get("insert linestart", "insert")
1196 if prefix.rstrip().endswith(':'):
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001197 self.newline_and_indent_event(event)
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001198 prefix = self.text.get("insert linestart", "insert")
1199 self.text.insert("insert", lines[0].strip())
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001200 if len(lines) > 1:
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001201 orig_base_indent = re.search(r'^([ \t]*)', lines[0]).group(0)
1202 new_base_indent = re.search(r'^([ \t]*)', prefix).group(0)
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001203 for line in lines[1:]:
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001204 if line.startswith(orig_base_indent):
1205 # replace orig base indentation with new indentation
1206 line = new_base_indent + line[len(orig_base_indent):]
1207 self.text.insert('insert', '\n'+line.rstrip())
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001208 finally:
1209 self.text.see("insert")
1210 self.text.undo_block_stop()
David Scherer7aced172000-08-15 01:13:23 +00001211
1212 def runit(self):
1213 line = self.text.get("iomark", "end-1c")
1214 # Strip off last newline and surrounding whitespace.
1215 # (To allow you to hit return twice to end a statement.)
1216 i = len(line)
1217 while i > 0 and line[i-1] in " \t":
1218 i = i-1
1219 if i > 0 and line[i-1] == "\n":
1220 i = i-1
1221 while i > 0 and line[i-1] in " \t":
1222 i = i-1
1223 line = line[:i]
1224 more = self.interp.runsource(line)
David Scherer7aced172000-08-15 01:13:23 +00001225
David Scherer7aced172000-08-15 01:13:23 +00001226 def open_stack_viewer(self, event=None):
Chui Tey5d2af632002-05-26 13:36:41 +00001227 if self.interp.rpcclt:
1228 return self.interp.remote_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +00001229 try:
1230 sys.last_traceback
1231 except:
1232 tkMessageBox.showerror("No stack trace",
1233 "There is no stack trace yet.\n"
1234 "(sys.last_traceback is not defined)",
1235 master=self.text)
1236 return
Florent Xiclunad630c042010-04-02 07:24:52 +00001237 from idlelib.StackViewer import StackBrowser
David Scherer7aced172000-08-15 01:13:23 +00001238 sv = StackBrowser(self.root, self.flist)
1239
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001240 def view_restart_mark(self, event=None):
1241 self.text.see("iomark")
1242 self.text.see("restart")
1243
1244 def restart_shell(self, event=None):
Terry Jan Reedyb98000a2012-01-31 02:09:25 -05001245 "Callback for Run/Restart Shell Cntl-F6"
1246 self.interp.restart_subprocess(with_cwd=True)
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001247
David Scherer7aced172000-08-15 01:13:23 +00001248 def showprompt(self):
1249 self.resetoutput()
1250 try:
1251 s = str(sys.ps1)
1252 except:
1253 s = ""
1254 self.console.write(s)
1255 self.text.mark_set("insert", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001256 self.set_line_and_column()
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +00001257 self.io.reset_undo()
David Scherer7aced172000-08-15 01:13:23 +00001258
1259 def resetoutput(self):
1260 source = self.text.get("iomark", "end-1c")
1261 if self.history:
1262 self.history.history_store(source)
1263 if self.text.get("end-2c") != "\n":
1264 self.text.insert("end-1c", "\n")
1265 self.text.mark_set("iomark", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001266 self.set_line_and_column()
David Scherer7aced172000-08-15 01:13:23 +00001267 sys.stdout.softspace = 0
1268
1269 def write(self, s, tags=()):
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001270 try:
1271 self.text.mark_gravity("iomark", "right")
1272 OutputWindow.write(self, s, tags, "iomark")
1273 self.text.mark_gravity("iomark", "left")
1274 except:
1275 pass
David Scherer7aced172000-08-15 01:13:23 +00001276 if self.canceled:
1277 self.canceled = 0
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001278 if not use_subprocess:
1279 raise KeyboardInterrupt
David Scherer7aced172000-08-15 01:13:23 +00001280
Andrew Svetlov5018db72012-11-01 22:39:14 +02001281 def rmenu_check_cut(self):
1282 try:
1283 if self.text.compare('sel.first', '<', 'iomark'):
1284 return 'disabled'
1285 except TclError: # no selection, so the index 'sel.first' doesn't exist
1286 return 'disabled'
1287 return super(PyShell, self).rmenu_check_cut()
1288
1289 def rmenu_check_paste(self):
1290 if self.text.compare('insert', '<', 'iomark'):
1291 return 'disabled'
1292 return super(PyShell, self).rmenu_check_paste()
1293
Serhiy Storchaka9abc8302013-01-25 15:30:35 +02001294class PseudoFile(io.TextIOBase):
David Scherer7aced172000-08-15 01:13:23 +00001295
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001296 def __init__(self, shell, tags, encoding=None):
David Scherer7aced172000-08-15 01:13:23 +00001297 self.shell = shell
1298 self.tags = tags
Chui Tey5d2af632002-05-26 13:36:41 +00001299 self.softspace = 0
Serhiy Storchaka9abc8302013-01-25 15:30:35 +02001300 self._encoding = encoding
David Scherer7aced172000-08-15 01:13:23 +00001301
Serhiy Storchaka9abc8302013-01-25 15:30:35 +02001302 @property
1303 def encoding(self):
1304 return self._encoding
David Scherer7aced172000-08-15 01:13:23 +00001305
Serhiy Storchaka9abc8302013-01-25 15:30:35 +02001306 @property
1307 def name(self):
1308 return '<%s>' % self.tags
David Scherer7aced172000-08-15 01:13:23 +00001309
1310 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001311 return True
David Scherer7aced172000-08-15 01:13:23 +00001312
Serhiy Storchaka9abc8302013-01-25 15:30:35 +02001313
1314class PseudoOutputFile(PseudoFile):
1315
1316 def writable(self):
1317 return True
Martin v. Löwise2b56242012-07-25 10:56:22 +02001318
1319 def write(self, s):
Serhiy Storchaka9abc8302013-01-25 15:30:35 +02001320 if self.closed:
1321 raise ValueError("write to closed file")
1322 if not isinstance(s, (basestring, bytearray)):
1323 raise TypeError('must be string, not ' + type(s).__name__)
1324 return self.shell.write(s, self.tags)
1325
1326
1327class PseudoInputFile(PseudoFile):
1328
1329 def __init__(self, shell, tags, encoding=None):
1330 PseudoFile.__init__(self, shell, tags, encoding)
1331 self._line_buffer = ''
1332
1333 def readable(self):
1334 return True
1335
1336 def read(self, size=-1):
1337 if self.closed:
1338 raise ValueError("read from closed file")
1339 if size is None:
1340 size = -1
1341 elif not isinstance(size, int):
1342 raise TypeError('must be int, not ' + type(size).__name__)
1343 result = self._line_buffer
1344 self._line_buffer = ''
1345 if size < 0:
1346 while True:
1347 line = self.shell.readline()
1348 if not line: break
1349 result += line
1350 else:
1351 while len(result) < size:
1352 line = self.shell.readline()
1353 if not line: break
1354 result += line
1355 self._line_buffer = result[size:]
1356 result = result[:size]
1357 return result
1358
1359 def readline(self, size=-1):
1360 if self.closed:
1361 raise ValueError("read from closed file")
1362 if size is None:
1363 size = -1
1364 elif not isinstance(size, int):
1365 raise TypeError('must be int, not ' + type(size).__name__)
1366 line = self._line_buffer or self.shell.readline()
1367 if size < 0:
1368 size = len(line)
1369 self._line_buffer = line[size:]
1370 return line[:size]
Martin v. Löwise2b56242012-07-25 10:56:22 +02001371
Roger Serwy53dc4f02013-04-11 19:13:21 -05001372 def close(self):
1373 self.shell.close()
1374
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001375
David Scherer7aced172000-08-15 01:13:23 +00001376usage_msg = """\
David Scherer7aced172000-08-15 01:13:23 +00001377
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001378USAGE: idle [-deins] [-t title] [file]*
1379 idle [-dns] [-t title] (-c cmd | -r file) [arg]*
1380 idle [-dns] [-t title] - [arg]*
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001381
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001382 -h print this help message and exit
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001383 -n run IDLE without a subprocess (see Help/IDLE Help for details)
David Scherer7aced172000-08-15 01:13:23 +00001384
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001385The following options will override the IDLE 'settings' configuration:
Kurt B. Kaiser96d88422001-07-17 04:59:01 +00001386
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001387 -e open an edit window
1388 -i open a shell window
1389
1390The following options imply -i and will open a shell:
1391
1392 -c cmd run the command in a shell, or
1393 -r file run script from file
1394
1395 -d enable the debugger
1396 -s run $IDLESTARTUP or $PYTHONSTARTUP before anything else
1397 -t title set title of shell window
1398
1399A default edit window will be bypassed when -c, -r, or - are used.
1400
1401[arg]* are passed to the command (-c) or script (-r) in sys.argv[1:].
1402
1403Examples:
1404
1405idle
1406 Open an edit window or shell depending on IDLE's configuration.
1407
1408idle foo.py foobar.py
1409 Edit the files, also open a shell if configured to start with shell.
1410
1411idle -est "Baz" foo.py
1412 Run $IDLESTARTUP or $PYTHONSTARTUP, edit foo.py, and open a shell
1413 window with the title "Baz".
1414
1415idle -c "import sys; print sys.argv" "foo"
1416 Open a shell window and run the command, passing "-c" in sys.argv[0]
1417 and "foo" in sys.argv[1].
1418
1419idle -d -s -r foo.py "Hello World"
1420 Open a shell window, run a startup script, enable the debugger, and
1421 run foo.py, passing "foo.py" in sys.argv[0] and "Hello World" in
1422 sys.argv[1].
1423
1424echo "import sys; print sys.argv" | idle - "foobar"
1425 Open a shell window, run the script piped in, passing '' in sys.argv[0]
1426 and "foobar" in sys.argv[1].
David Scherer7aced172000-08-15 01:13:23 +00001427"""
1428
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001429def main():
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001430 global flist, root, use_subprocess
David Scherer7aced172000-08-15 01:13:23 +00001431
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001432 use_subprocess = True
Roger Serwy34d0c662013-03-31 23:28:55 -05001433 enable_shell = False
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001434 enable_edit = False
1435 debug = False
1436 cmd = None
1437 script = None
1438 startup = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001439 try:
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001440 opts, args = getopt.getopt(sys.argv[1:], "c:deihnr:st:")
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001441 except getopt.error, msg:
1442 sys.stderr.write("Error: %s\n" % str(msg))
1443 sys.stderr.write(usage_msg)
1444 sys.exit(2)
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001445 for o, a in opts:
1446 if o == '-c':
1447 cmd = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001448 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001449 if o == '-d':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001450 debug = True
1451 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001452 if o == '-e':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001453 enable_edit = True
1454 if o == '-h':
1455 sys.stdout.write(usage_msg)
1456 sys.exit()
1457 if o == '-i':
1458 enable_shell = True
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001459 if o == '-n':
1460 use_subprocess = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001461 if o == '-r':
1462 script = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001463 if os.path.isfile(script):
1464 pass
1465 else:
1466 print "No script file: ", script
1467 sys.exit()
1468 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001469 if o == '-s':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001470 startup = True
1471 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001472 if o == '-t':
1473 PyShell.shell_title = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001474 enable_shell = True
1475 if args and args[0] == '-':
1476 cmd = sys.stdin.read()
1477 enable_shell = True
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001478 # process sys.argv and sys.path:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001479 for i in range(len(sys.path)):
1480 sys.path[i] = os.path.abspath(sys.path[i])
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001481 if args and args[0] == '-':
1482 sys.argv = [''] + args[1:]
1483 elif cmd:
1484 sys.argv = ['-c'] + args
1485 elif script:
1486 sys.argv = [script] + args
1487 elif args:
1488 enable_edit = True
1489 pathx = []
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001490 for filename in args:
1491 pathx.append(os.path.dirname(filename))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001492 for dir in pathx:
1493 dir = os.path.abspath(dir)
Florent Xiclunad630c042010-04-02 07:24:52 +00001494 if dir not in sys.path:
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001495 sys.path.insert(0, dir)
Kurt B. Kaiserff002b92002-12-21 21:39:11 +00001496 else:
1497 dir = os.getcwd()
1498 if not dir in sys.path:
1499 sys.path.insert(0, dir)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001500 # check the IDLE settings configuration (but command line overrides)
1501 edit_start = idleConf.GetOption('main', 'General',
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001502 'editor-on-startup', type='bool')
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001503 enable_edit = enable_edit or edit_start
Roger Serwy34d0c662013-03-31 23:28:55 -05001504 enable_shell = enable_shell or not enable_edit
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001505 # start editor and/or shell windows:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001506 root = Tk(className="Idle")
Ronald Oussoren19302d92006-06-11 14:33:36 +00001507
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001508 fixwordbreaks(root)
1509 root.withdraw()
1510 flist = PyShellFileList(root)
Ronald Oussoren19302d92006-06-11 14:33:36 +00001511 macosxSupport.setupApp(root, flist)
1512
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001513 if enable_edit:
1514 if not (cmd or script):
Andrew Svetlov7c010ee2012-03-21 13:35:08 +02001515 for filename in args[:]:
1516 if flist.open(filename) is None:
1517 # filename is a directory actually, disconsider it
1518 args.remove(filename)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001519 if not args:
1520 flist.new()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001521 if enable_shell:
Ronald Oussoren19302d92006-06-11 14:33:36 +00001522 shell = flist.open_shell()
1523 if not shell:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001524 return # couldn't open shell
Ronald Oussoren19302d92006-06-11 14:33:36 +00001525
1526 if macosxSupport.runningAsOSXApp() and flist.dict:
1527 # On OSX: when the user has double-clicked on a file that causes
Tim Peters4f96f1f2006-06-11 19:42:51 +00001528 # IDLE to be launched the shell window will open just in front of
1529 # the file she wants to see. Lower the interpreter window when
Ronald Oussoren19302d92006-06-11 14:33:36 +00001530 # there are open files.
1531 shell.top.lower()
1532
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001533 shell = flist.pyshell
1534 # handle remaining options:
1535 if debug:
1536 shell.open_debugger()
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001537 if startup:
1538 filename = os.environ.get("IDLESTARTUP") or \
1539 os.environ.get("PYTHONSTARTUP")
1540 if filename and os.path.isfile(filename):
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001541 shell.interp.execfile(filename)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001542 if shell and cmd or script:
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001543 shell.interp.runcommand("""if 1:
1544 import sys as _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001545 _sys.argv = %r
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001546 del _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001547 \n""" % (sys.argv,))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001548 if cmd:
1549 shell.interp.execsource(cmd)
1550 elif script:
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001551 shell.interp.prepend_syspath(script)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001552 shell.interp.execfile(script)
Ronald Oussoren19302d92006-06-11 14:33:36 +00001553
Ned Deily2a6f4b32011-01-30 00:18:47 +00001554 # Check for problematic OS X Tk versions and print a warning message
1555 # in the IDLE shell window; this is less intrusive than always opening
1556 # a separate window.
1557 tkversionwarning = macosxSupport.tkVersionWarning(root)
1558 if tkversionwarning:
1559 shell.interp.runcommand(''.join(("print('", tkversionwarning, "')")))
1560
Terry Jan Reedyeaa7e782012-05-26 20:33:32 -04001561 while flist.inversedict: # keep IDLE running while files are open.
1562 root.mainloop()
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001563 root.destroy()
1564
David Scherer7aced172000-08-15 01:13:23 +00001565if __name__ == "__main__":
Kurt B. Kaiser9e8b8282003-06-15 17:38:45 +00001566 sys.modules['PyShell'] = sys.modules['__main__']
David Scherer7aced172000-08-15 01:13:23 +00001567 main()