blob: 81af85a84044e4f53ed3df3e69c1a2f3c54a9015 [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():
847 del menu_specs[-3]
848 menu_specs[-2] = ("windows", "_Window")
849
850
David Scherer7aced172000-08-15 01:13:23 +0000851 # New classes
Florent Xiclunad630c042010-04-02 07:24:52 +0000852 from idlelib.IdleHistory import History
David Scherer7aced172000-08-15 01:13:23 +0000853
854 def __init__(self, flist=None):
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000855 if use_subprocess:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000856 ms = self.menu_specs
857 if ms[2][0] != "shell":
Kurt B. Kaiser7ae35482006-08-16 21:45:59 +0000858 ms.insert(2, ("shell", "She_ll"))
David Scherer7aced172000-08-15 01:13:23 +0000859 self.interp = ModifiedInterpreter(self)
860 if flist is None:
861 root = Tk()
862 fixwordbreaks(root)
863 root.withdraw()
864 flist = PyShellFileList(root)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000865 #
David Scherer7aced172000-08-15 01:13:23 +0000866 OutputWindow.__init__(self, flist, None, None)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000867 #
Kurt B. Kaiser6af44982005-01-19 00:22:59 +0000868## self.config(usetabs=1, indentwidth=8, context_use_ps1=1)
869 self.usetabs = True
870 # indentwidth must be 8 when using tabs. See note in EditorWindow:
871 self.indentwidth = 8
872 self.context_use_ps1 = True
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000873 #
David Scherer7aced172000-08-15 01:13:23 +0000874 text = self.text
875 text.configure(wrap="char")
876 text.bind("<<newline-and-indent>>", self.enter_callback)
877 text.bind("<<plain-newline-and-indent>>", self.linefeed_callback)
878 text.bind("<<interrupt-execution>>", self.cancel_callback)
David Scherer7aced172000-08-15 01:13:23 +0000879 text.bind("<<end-of-file>>", self.eof_callback)
880 text.bind("<<open-stack-viewer>>", self.open_stack_viewer)
Kurt B. Kaiser57bfe5d2003-05-10 00:09:52 +0000881 text.bind("<<toggle-debugger>>", self.toggle_debugger)
David Scherer7aced172000-08-15 01:13:23 +0000882 text.bind("<<toggle-jit-stack-viewer>>", self.toggle_jit_stack_viewer)
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000883 if use_subprocess:
884 text.bind("<<view-restart>>", self.view_restart_mark)
885 text.bind("<<restart-shell>>", self.restart_shell)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000886 #
David Scherer7aced172000-08-15 01:13:23 +0000887 self.save_stdout = sys.stdout
888 self.save_stderr = sys.stderr
889 self.save_stdin = sys.stdin
Florent Xiclunad630c042010-04-02 07:24:52 +0000890 from idlelib import IOBinding
Serhiy Storchaka9abc8302013-01-25 15:30:35 +0200891 self.stdin = PseudoInputFile(self, "stdin", IOBinding.encoding)
892 self.stdout = PseudoOutputFile(self, "stdout", IOBinding.encoding)
893 self.stderr = PseudoOutputFile(self, "stderr", IOBinding.encoding)
894 self.console = PseudoOutputFile(self, "console", IOBinding.encoding)
Chui Tey5d2af632002-05-26 13:36:41 +0000895 if not use_subprocess:
896 sys.stdout = self.stdout
897 sys.stderr = self.stderr
Martin v. Löwise2b56242012-07-25 10:56:22 +0200898 sys.stdin = self.stdin
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000899 #
David Scherer7aced172000-08-15 01:13:23 +0000900 self.history = self.History(self.text)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000901 #
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000902 self.pollinterval = 50 # millisec
Chui Tey5d2af632002-05-26 13:36:41 +0000903
Kurt B. Kaiser4d5bc602004-06-06 01:29:22 +0000904 def get_standard_extension_names(self):
905 return idleConf.GetExtensions(shell_only=True)
906
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000907 reading = False
908 executing = False
909 canceled = False
910 endoffile = False
911 closing = False
Roger Serwyad8cad32013-04-03 00:42:24 -0500912 _stop_readline_flag = False
David Scherer7aced172000-08-15 01:13:23 +0000913
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +0000914 def set_warning_stream(self, stream):
Skip Montanarod9161422004-07-06 21:53:27 +0000915 global warning_stream
916 warning_stream = stream
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +0000917
918 def get_warning_stream(self):
919 return warning_stream
920
David Scherer7aced172000-08-15 01:13:23 +0000921 def toggle_debugger(self, event=None):
922 if self.executing:
923 tkMessageBox.showerror("Don't debug now",
924 "You can only toggle the debugger when idle",
925 master=self.text)
926 self.set_debugger_indicator()
927 return "break"
928 else:
929 db = self.interp.getdebugger()
930 if db:
931 self.close_debugger()
932 else:
933 self.open_debugger()
934
935 def set_debugger_indicator(self):
936 db = self.interp.getdebugger()
937 self.setvar("<<toggle-debugger>>", not not db)
938
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000939 def toggle_jit_stack_viewer(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +0000940 pass # All we need is the variable
941
942 def close_debugger(self):
943 db = self.interp.getdebugger()
944 if db:
945 self.interp.setdebugger(None)
946 db.close()
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000947 if self.interp.rpcclt:
948 RemoteDebugger.close_remote_debugger(self.interp.rpcclt)
David Scherer7aced172000-08-15 01:13:23 +0000949 self.resetoutput()
950 self.console.write("[DEBUG OFF]\n")
951 sys.ps1 = ">>> "
952 self.showprompt()
953 self.set_debugger_indicator()
954
955 def open_debugger(self):
Chui Tey5d2af632002-05-26 13:36:41 +0000956 if self.interp.rpcclt:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000957 dbg_gui = RemoteDebugger.start_remote_debugger(self.interp.rpcclt,
958 self)
959 else:
960 dbg_gui = Debugger.Debugger(self)
961 self.interp.setdebugger(dbg_gui)
962 dbg_gui.load_breakpoints()
Chui Tey5d2af632002-05-26 13:36:41 +0000963 sys.ps1 = "[DEBUG ON]\n>>> "
964 self.showprompt()
965 self.set_debugger_indicator()
966
David Scherer7aced172000-08-15 01:13:23 +0000967 def beginexecuting(self):
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000968 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +0000969 self.resetoutput()
970 self.executing = 1
David Scherer7aced172000-08-15 01:13:23 +0000971
972 def endexecuting(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000973 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +0000974 self.executing = 0
975 self.canceled = 0
Chui Tey5d2af632002-05-26 13:36:41 +0000976 self.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000977
978 def close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000979 "Extend EditorWindow.close()"
David Scherer7aced172000-08-15 01:13:23 +0000980 if self.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000981 response = tkMessageBox.askokcancel(
David Scherer7aced172000-08-15 01:13:23 +0000982 "Kill?",
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000983 "The program is still running!\n Do you want to kill it?",
David Scherer7aced172000-08-15 01:13:23 +0000984 default="ok",
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000985 parent=self.text)
Benjamin Peterson5b63acd2008-03-29 15:24:25 +0000986 if response is False:
David Scherer7aced172000-08-15 01:13:23 +0000987 return "cancel"
Roger Serwyad8cad32013-04-03 00:42:24 -0500988 self.stop_readline()
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +0000989 self.canceled = True
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000990 self.closing = True
991 # Wait for poll_subprocess() rescheduling to stop
992 self.text.after(2 * self.pollinterval, self.close2)
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000993
994 def close2(self):
995 return EditorWindow.close(self)
David Scherer7aced172000-08-15 01:13:23 +0000996
997 def _close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000998 "Extend EditorWindow._close(), shut down debugger and execution server"
David Scherer7aced172000-08-15 01:13:23 +0000999 self.close_debugger()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001000 if use_subprocess:
1001 self.interp.kill_subprocess()
David Scherer7aced172000-08-15 01:13:23 +00001002 # Restore std streams
1003 sys.stdout = self.save_stdout
1004 sys.stderr = self.save_stderr
1005 sys.stdin = self.save_stdin
1006 # Break cycles
1007 self.interp = None
1008 self.console = None
David Scherer7aced172000-08-15 01:13:23 +00001009 self.flist.pyshell = None
1010 self.history = None
Kurt B. Kaiser83118c62002-06-24 17:03:37 +00001011 EditorWindow._close(self)
David Scherer7aced172000-08-15 01:13:23 +00001012
1013 def ispythonsource(self, filename):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +00001014 "Override EditorWindow method: never remove the colorizer"
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001015 return True
David Scherer7aced172000-08-15 01:13:23 +00001016
1017 def short_title(self):
1018 return self.shell_title
1019
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +00001020 COPYRIGHT = \
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001021 'Type "copyright", "credits" or "license()" for more information.'
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +00001022
David Scherer7aced172000-08-15 01:13:23 +00001023 def begin(self):
1024 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001025 if use_subprocess:
1026 nosub = ''
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001027 client = self.interp.start_subprocess()
1028 if not client:
1029 self.close()
Kurt B. Kaiser76637292004-01-21 22:10:01 +00001030 return False
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001031 else:
1032 nosub = "==== No Subprocess ===="
Raymond Hettingerbf3f69e2009-01-26 23:29:09 +00001033 self.write("Python %s on %s\n%s\n%s" %
1034 (sys.version, sys.platform, self.COPYRIGHT, nosub))
David Scherer7aced172000-08-15 01:13:23 +00001035 self.showprompt()
Georg Brandl6634bf22008-05-20 07:13:37 +00001036 import Tkinter
1037 Tkinter._default_root = None # 03Jan04 KBK What's this?
Kurt B. Kaiser76637292004-01-21 22:10:01 +00001038 return True
David Scherer7aced172000-08-15 01:13:23 +00001039
Roger Serwyad8cad32013-04-03 00:42:24 -05001040 def stop_readline(self):
1041 if not self.reading: # no nested mainloop to exit.
1042 return
1043 self._stop_readline_flag = True
1044 self.top.quit()
1045
David Scherer7aced172000-08-15 01:13:23 +00001046 def readline(self):
1047 save = self.reading
1048 try:
1049 self.reading = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001050 self.top.mainloop() # nested mainloop()
David Scherer7aced172000-08-15 01:13:23 +00001051 finally:
1052 self.reading = save
Roger Serwyad8cad32013-04-03 00:42:24 -05001053 if self._stop_readline_flag:
1054 self._stop_readline_flag = False
1055 return ""
David Scherer7aced172000-08-15 01:13:23 +00001056 line = self.text.get("iomark", "end-1c")
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001057 if len(line) == 0: # may be EOF if we quit our mainloop with Ctrl-C
1058 line = "\n"
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001059 if isinstance(line, unicode):
Florent Xiclunad630c042010-04-02 07:24:52 +00001060 from idlelib import IOBinding
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001061 try:
1062 line = line.encode(IOBinding.encoding)
1063 except UnicodeError:
1064 pass
David Scherer7aced172000-08-15 01:13:23 +00001065 self.resetoutput()
1066 if self.canceled:
1067 self.canceled = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001068 if not use_subprocess:
1069 raise KeyboardInterrupt
David Scherer7aced172000-08-15 01:13:23 +00001070 if self.endoffile:
1071 self.endoffile = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001072 line = ""
David Scherer7aced172000-08-15 01:13:23 +00001073 return line
1074
1075 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001076 return True
David Scherer7aced172000-08-15 01:13:23 +00001077
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001078 def cancel_callback(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +00001079 try:
1080 if self.text.compare("sel.first", "!=", "sel.last"):
1081 return # Active selection -- always use default binding
1082 except:
1083 pass
1084 if not (self.executing or self.reading):
1085 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001086 self.interp.write("KeyboardInterrupt\n")
David Scherer7aced172000-08-15 01:13:23 +00001087 self.showprompt()
1088 return "break"
1089 self.endoffile = 0
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001090 self.canceled = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001091 if (self.executing and self.interp.rpcclt):
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +00001092 if self.interp.getdebugger():
1093 self.interp.restart_subprocess()
1094 else:
1095 self.interp.interrupt_subprocess()
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001096 if self.reading:
1097 self.top.quit() # exit the nested mainloop() in readline()
David Scherer7aced172000-08-15 01:13:23 +00001098 return "break"
1099
1100 def eof_callback(self, event):
1101 if self.executing and not self.reading:
1102 return # Let the default binding (delete next char) take over
1103 if not (self.text.compare("iomark", "==", "insert") and
1104 self.text.compare("insert", "==", "end-1c")):
1105 return # Let the default binding (delete next char) take over
1106 if not self.executing:
David Scherer7aced172000-08-15 01:13:23 +00001107 self.resetoutput()
1108 self.close()
1109 else:
1110 self.canceled = 0
1111 self.endoffile = 1
1112 self.top.quit()
1113 return "break"
1114
David Scherer7aced172000-08-15 01:13:23 +00001115 def linefeed_callback(self, event):
1116 # Insert a linefeed without entering anything (still autoindented)
1117 if self.reading:
1118 self.text.insert("insert", "\n")
1119 self.text.see("insert")
1120 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001121 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001122 return "break"
1123
1124 def enter_callback(self, event):
1125 if self.executing and not self.reading:
1126 return # Let the default binding (insert '\n') take over
1127 # If some text is selected, recall the selection
1128 # (but only if this before the I/O mark)
1129 try:
1130 sel = self.text.get("sel.first", "sel.last")
1131 if sel:
1132 if self.text.compare("sel.last", "<=", "iomark"):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001133 self.recall(sel, event)
David Scherer7aced172000-08-15 01:13:23 +00001134 return "break"
1135 except:
1136 pass
1137 # If we're strictly before the line containing iomark, recall
1138 # the current line, less a leading prompt, less leading or
1139 # trailing whitespace
1140 if self.text.compare("insert", "<", "iomark linestart"):
1141 # Check if there's a relevant stdin range -- if so, use it
1142 prev = self.text.tag_prevrange("stdin", "insert")
1143 if prev and self.text.compare("insert", "<", prev[1]):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001144 self.recall(self.text.get(prev[0], prev[1]), event)
David Scherer7aced172000-08-15 01:13:23 +00001145 return "break"
1146 next = self.text.tag_nextrange("stdin", "insert")
1147 if next and self.text.compare("insert lineend", ">=", next[0]):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001148 self.recall(self.text.get(next[0], next[1]), event)
David Scherer7aced172000-08-15 01:13:23 +00001149 return "break"
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001150 # No stdin mark -- just get the current line, less any prompt
Kurt B. Kaiserb1754452005-11-18 22:05:48 +00001151 indices = self.text.tag_nextrange("console", "insert linestart")
1152 if indices and \
1153 self.text.compare(indices[0], "<=", "insert linestart"):
1154 self.recall(self.text.get(indices[1], "insert lineend"), event)
1155 else:
1156 self.recall(self.text.get("insert linestart", "insert lineend"), event)
David Scherer7aced172000-08-15 01:13:23 +00001157 return "break"
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001158 # If we're between the beginning of the line and the iomark, i.e.
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001159 # in the prompt area, move to the end of the prompt
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001160 if self.text.compare("insert", "<", "iomark"):
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001161 self.text.mark_set("insert", "iomark")
David Scherer7aced172000-08-15 01:13:23 +00001162 # If we're in the current input and there's only whitespace
1163 # beyond the cursor, erase that whitespace first
1164 s = self.text.get("insert", "end-1c")
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001165 if s and not s.strip():
David Scherer7aced172000-08-15 01:13:23 +00001166 self.text.delete("insert", "end-1c")
1167 # If we're in the current input before its last line,
1168 # insert a newline right at the insert point
1169 if self.text.compare("insert", "<", "end-1c linestart"):
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001170 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001171 return "break"
1172 # We're in the last line; append a newline and submit it
1173 self.text.mark_set("insert", "end-1c")
1174 if self.reading:
1175 self.text.insert("insert", "\n")
1176 self.text.see("insert")
1177 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001178 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001179 self.text.tag_add("stdin", "iomark", "end-1c")
1180 self.text.update_idletasks()
1181 if self.reading:
1182 self.top.quit() # Break out of recursive mainloop() in raw_input()
1183 else:
1184 self.runit()
1185 return "break"
1186
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001187 def recall(self, s, event):
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001188 # remove leading and trailing empty or whitespace lines
1189 s = re.sub(r'^\s*\n', '' , s)
1190 s = re.sub(r'\n\s*$', '', s)
1191 lines = s.split('\n')
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001192 self.text.undo_block_start()
1193 try:
1194 self.text.tag_remove("sel", "1.0", "end")
1195 self.text.mark_set("insert", "end-1c")
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001196 prefix = self.text.get("insert linestart", "insert")
1197 if prefix.rstrip().endswith(':'):
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001198 self.newline_and_indent_event(event)
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001199 prefix = self.text.get("insert linestart", "insert")
1200 self.text.insert("insert", lines[0].strip())
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001201 if len(lines) > 1:
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001202 orig_base_indent = re.search(r'^([ \t]*)', lines[0]).group(0)
1203 new_base_indent = re.search(r'^([ \t]*)', prefix).group(0)
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001204 for line in lines[1:]:
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001205 if line.startswith(orig_base_indent):
1206 # replace orig base indentation with new indentation
1207 line = new_base_indent + line[len(orig_base_indent):]
1208 self.text.insert('insert', '\n'+line.rstrip())
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001209 finally:
1210 self.text.see("insert")
1211 self.text.undo_block_stop()
David Scherer7aced172000-08-15 01:13:23 +00001212
1213 def runit(self):
1214 line = self.text.get("iomark", "end-1c")
1215 # Strip off last newline and surrounding whitespace.
1216 # (To allow you to hit return twice to end a statement.)
1217 i = len(line)
1218 while i > 0 and line[i-1] in " \t":
1219 i = i-1
1220 if i > 0 and line[i-1] == "\n":
1221 i = i-1
1222 while i > 0 and line[i-1] in " \t":
1223 i = i-1
1224 line = line[:i]
1225 more = self.interp.runsource(line)
David Scherer7aced172000-08-15 01:13:23 +00001226
David Scherer7aced172000-08-15 01:13:23 +00001227 def open_stack_viewer(self, event=None):
Chui Tey5d2af632002-05-26 13:36:41 +00001228 if self.interp.rpcclt:
1229 return self.interp.remote_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +00001230 try:
1231 sys.last_traceback
1232 except:
1233 tkMessageBox.showerror("No stack trace",
1234 "There is no stack trace yet.\n"
1235 "(sys.last_traceback is not defined)",
1236 master=self.text)
1237 return
Florent Xiclunad630c042010-04-02 07:24:52 +00001238 from idlelib.StackViewer import StackBrowser
David Scherer7aced172000-08-15 01:13:23 +00001239 sv = StackBrowser(self.root, self.flist)
1240
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001241 def view_restart_mark(self, event=None):
1242 self.text.see("iomark")
1243 self.text.see("restart")
1244
1245 def restart_shell(self, event=None):
Terry Jan Reedyb98000a2012-01-31 02:09:25 -05001246 "Callback for Run/Restart Shell Cntl-F6"
1247 self.interp.restart_subprocess(with_cwd=True)
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001248
David Scherer7aced172000-08-15 01:13:23 +00001249 def showprompt(self):
1250 self.resetoutput()
1251 try:
1252 s = str(sys.ps1)
1253 except:
1254 s = ""
1255 self.console.write(s)
1256 self.text.mark_set("insert", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001257 self.set_line_and_column()
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +00001258 self.io.reset_undo()
David Scherer7aced172000-08-15 01:13:23 +00001259
1260 def resetoutput(self):
1261 source = self.text.get("iomark", "end-1c")
1262 if self.history:
1263 self.history.history_store(source)
1264 if self.text.get("end-2c") != "\n":
1265 self.text.insert("end-1c", "\n")
1266 self.text.mark_set("iomark", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001267 self.set_line_and_column()
David Scherer7aced172000-08-15 01:13:23 +00001268 sys.stdout.softspace = 0
1269
1270 def write(self, s, tags=()):
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001271 try:
1272 self.text.mark_gravity("iomark", "right")
1273 OutputWindow.write(self, s, tags, "iomark")
1274 self.text.mark_gravity("iomark", "left")
1275 except:
1276 pass
David Scherer7aced172000-08-15 01:13:23 +00001277 if self.canceled:
1278 self.canceled = 0
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001279 if not use_subprocess:
1280 raise KeyboardInterrupt
David Scherer7aced172000-08-15 01:13:23 +00001281
Andrew Svetlov5018db72012-11-01 22:39:14 +02001282 def rmenu_check_cut(self):
1283 try:
1284 if self.text.compare('sel.first', '<', 'iomark'):
1285 return 'disabled'
1286 except TclError: # no selection, so the index 'sel.first' doesn't exist
1287 return 'disabled'
1288 return super(PyShell, self).rmenu_check_cut()
1289
1290 def rmenu_check_paste(self):
1291 if self.text.compare('insert', '<', 'iomark'):
1292 return 'disabled'
1293 return super(PyShell, self).rmenu_check_paste()
1294
Serhiy Storchaka9abc8302013-01-25 15:30:35 +02001295class PseudoFile(io.TextIOBase):
David Scherer7aced172000-08-15 01:13:23 +00001296
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001297 def __init__(self, shell, tags, encoding=None):
David Scherer7aced172000-08-15 01:13:23 +00001298 self.shell = shell
1299 self.tags = tags
Chui Tey5d2af632002-05-26 13:36:41 +00001300 self.softspace = 0
Serhiy Storchaka9abc8302013-01-25 15:30:35 +02001301 self._encoding = encoding
David Scherer7aced172000-08-15 01:13:23 +00001302
Serhiy Storchaka9abc8302013-01-25 15:30:35 +02001303 @property
1304 def encoding(self):
1305 return self._encoding
David Scherer7aced172000-08-15 01:13:23 +00001306
Serhiy Storchaka9abc8302013-01-25 15:30:35 +02001307 @property
1308 def name(self):
1309 return '<%s>' % self.tags
David Scherer7aced172000-08-15 01:13:23 +00001310
1311 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001312 return True
David Scherer7aced172000-08-15 01:13:23 +00001313
Serhiy Storchaka9abc8302013-01-25 15:30:35 +02001314
1315class PseudoOutputFile(PseudoFile):
1316
1317 def writable(self):
1318 return True
Martin v. Löwise2b56242012-07-25 10:56:22 +02001319
1320 def write(self, s):
Serhiy Storchaka9abc8302013-01-25 15:30:35 +02001321 if self.closed:
1322 raise ValueError("write to closed file")
1323 if not isinstance(s, (basestring, bytearray)):
1324 raise TypeError('must be string, not ' + type(s).__name__)
1325 return self.shell.write(s, self.tags)
1326
1327
1328class PseudoInputFile(PseudoFile):
1329
1330 def __init__(self, shell, tags, encoding=None):
1331 PseudoFile.__init__(self, shell, tags, encoding)
1332 self._line_buffer = ''
1333
1334 def readable(self):
1335 return True
1336
1337 def read(self, size=-1):
1338 if self.closed:
1339 raise ValueError("read from closed file")
1340 if size is None:
1341 size = -1
1342 elif not isinstance(size, int):
1343 raise TypeError('must be int, not ' + type(size).__name__)
1344 result = self._line_buffer
1345 self._line_buffer = ''
1346 if size < 0:
1347 while True:
1348 line = self.shell.readline()
1349 if not line: break
1350 result += line
1351 else:
1352 while len(result) < size:
1353 line = self.shell.readline()
1354 if not line: break
1355 result += line
1356 self._line_buffer = result[size:]
1357 result = result[:size]
1358 return result
1359
1360 def readline(self, size=-1):
1361 if self.closed:
1362 raise ValueError("read from closed file")
1363 if size is None:
1364 size = -1
1365 elif not isinstance(size, int):
1366 raise TypeError('must be int, not ' + type(size).__name__)
1367 line = self._line_buffer or self.shell.readline()
1368 if size < 0:
1369 size = len(line)
1370 self._line_buffer = line[size:]
1371 return line[:size]
Martin v. Löwise2b56242012-07-25 10:56:22 +02001372
Roger Serwy53dc4f02013-04-11 19:13:21 -05001373 def close(self):
1374 self.shell.close()
1375
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001376
David Scherer7aced172000-08-15 01:13:23 +00001377usage_msg = """\
David Scherer7aced172000-08-15 01:13:23 +00001378
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001379USAGE: idle [-deins] [-t title] [file]*
1380 idle [-dns] [-t title] (-c cmd | -r file) [arg]*
1381 idle [-dns] [-t title] - [arg]*
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001382
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001383 -h print this help message and exit
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001384 -n run IDLE without a subprocess (see Help/IDLE Help for details)
David Scherer7aced172000-08-15 01:13:23 +00001385
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001386The following options will override the IDLE 'settings' configuration:
Kurt B. Kaiser96d88422001-07-17 04:59:01 +00001387
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001388 -e open an edit window
1389 -i open a shell window
1390
1391The following options imply -i and will open a shell:
1392
1393 -c cmd run the command in a shell, or
1394 -r file run script from file
1395
1396 -d enable the debugger
1397 -s run $IDLESTARTUP or $PYTHONSTARTUP before anything else
1398 -t title set title of shell window
1399
1400A default edit window will be bypassed when -c, -r, or - are used.
1401
1402[arg]* are passed to the command (-c) or script (-r) in sys.argv[1:].
1403
1404Examples:
1405
1406idle
1407 Open an edit window or shell depending on IDLE's configuration.
1408
1409idle foo.py foobar.py
1410 Edit the files, also open a shell if configured to start with shell.
1411
1412idle -est "Baz" foo.py
1413 Run $IDLESTARTUP or $PYTHONSTARTUP, edit foo.py, and open a shell
1414 window with the title "Baz".
1415
1416idle -c "import sys; print sys.argv" "foo"
1417 Open a shell window and run the command, passing "-c" in sys.argv[0]
1418 and "foo" in sys.argv[1].
1419
1420idle -d -s -r foo.py "Hello World"
1421 Open a shell window, run a startup script, enable the debugger, and
1422 run foo.py, passing "foo.py" in sys.argv[0] and "Hello World" in
1423 sys.argv[1].
1424
1425echo "import sys; print sys.argv" | idle - "foobar"
1426 Open a shell window, run the script piped in, passing '' in sys.argv[0]
1427 and "foobar" in sys.argv[1].
David Scherer7aced172000-08-15 01:13:23 +00001428"""
1429
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001430def main():
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001431 global flist, root, use_subprocess
David Scherer7aced172000-08-15 01:13:23 +00001432
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001433 use_subprocess = True
Roger Serwy34d0c662013-03-31 23:28:55 -05001434 enable_shell = False
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001435 enable_edit = False
1436 debug = False
1437 cmd = None
1438 script = None
1439 startup = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001440 try:
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001441 opts, args = getopt.getopt(sys.argv[1:], "c:deihnr:st:")
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001442 except getopt.error, msg:
1443 sys.stderr.write("Error: %s\n" % str(msg))
1444 sys.stderr.write(usage_msg)
1445 sys.exit(2)
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001446 for o, a in opts:
1447 if o == '-c':
1448 cmd = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001449 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001450 if o == '-d':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001451 debug = True
1452 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001453 if o == '-e':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001454 enable_edit = True
1455 if o == '-h':
1456 sys.stdout.write(usage_msg)
1457 sys.exit()
1458 if o == '-i':
1459 enable_shell = True
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001460 if o == '-n':
1461 use_subprocess = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001462 if o == '-r':
1463 script = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001464 if os.path.isfile(script):
1465 pass
1466 else:
1467 print "No script file: ", script
1468 sys.exit()
1469 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001470 if o == '-s':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001471 startup = True
1472 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001473 if o == '-t':
1474 PyShell.shell_title = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001475 enable_shell = True
1476 if args and args[0] == '-':
1477 cmd = sys.stdin.read()
1478 enable_shell = True
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001479 # process sys.argv and sys.path:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001480 for i in range(len(sys.path)):
1481 sys.path[i] = os.path.abspath(sys.path[i])
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001482 if args and args[0] == '-':
1483 sys.argv = [''] + args[1:]
1484 elif cmd:
1485 sys.argv = ['-c'] + args
1486 elif script:
1487 sys.argv = [script] + args
1488 elif args:
1489 enable_edit = True
1490 pathx = []
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001491 for filename in args:
1492 pathx.append(os.path.dirname(filename))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001493 for dir in pathx:
1494 dir = os.path.abspath(dir)
Florent Xiclunad630c042010-04-02 07:24:52 +00001495 if dir not in sys.path:
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001496 sys.path.insert(0, dir)
Kurt B. Kaiserff002b92002-12-21 21:39:11 +00001497 else:
1498 dir = os.getcwd()
1499 if not dir in sys.path:
1500 sys.path.insert(0, dir)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001501 # check the IDLE settings configuration (but command line overrides)
1502 edit_start = idleConf.GetOption('main', 'General',
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001503 'editor-on-startup', type='bool')
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001504 enable_edit = enable_edit or edit_start
Roger Serwy34d0c662013-03-31 23:28:55 -05001505 enable_shell = enable_shell or not enable_edit
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001506 # start editor and/or shell windows:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001507 root = Tk(className="Idle")
Ronald Oussoren19302d92006-06-11 14:33:36 +00001508
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001509 fixwordbreaks(root)
1510 root.withdraw()
1511 flist = PyShellFileList(root)
Ronald Oussoren19302d92006-06-11 14:33:36 +00001512 macosxSupport.setupApp(root, flist)
1513
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001514 if enable_edit:
1515 if not (cmd or script):
Andrew Svetlov7c010ee2012-03-21 13:35:08 +02001516 for filename in args[:]:
1517 if flist.open(filename) is None:
1518 # filename is a directory actually, disconsider it
1519 args.remove(filename)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001520 if not args:
1521 flist.new()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001522 if enable_shell:
Ronald Oussoren19302d92006-06-11 14:33:36 +00001523 shell = flist.open_shell()
1524 if not shell:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001525 return # couldn't open shell
Ronald Oussoren19302d92006-06-11 14:33:36 +00001526
1527 if macosxSupport.runningAsOSXApp() and flist.dict:
1528 # On OSX: when the user has double-clicked on a file that causes
Tim Peters4f96f1f2006-06-11 19:42:51 +00001529 # IDLE to be launched the shell window will open just in front of
1530 # the file she wants to see. Lower the interpreter window when
Ronald Oussoren19302d92006-06-11 14:33:36 +00001531 # there are open files.
1532 shell.top.lower()
1533
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001534 shell = flist.pyshell
1535 # handle remaining options:
1536 if debug:
1537 shell.open_debugger()
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001538 if startup:
1539 filename = os.environ.get("IDLESTARTUP") or \
1540 os.environ.get("PYTHONSTARTUP")
1541 if filename and os.path.isfile(filename):
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001542 shell.interp.execfile(filename)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001543 if shell and cmd or script:
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001544 shell.interp.runcommand("""if 1:
1545 import sys as _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001546 _sys.argv = %r
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001547 del _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001548 \n""" % (sys.argv,))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001549 if cmd:
1550 shell.interp.execsource(cmd)
1551 elif script:
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001552 shell.interp.prepend_syspath(script)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001553 shell.interp.execfile(script)
Ronald Oussoren19302d92006-06-11 14:33:36 +00001554
Ned Deily2a6f4b32011-01-30 00:18:47 +00001555 # Check for problematic OS X Tk versions and print a warning message
1556 # in the IDLE shell window; this is less intrusive than always opening
1557 # a separate window.
1558 tkversionwarning = macosxSupport.tkVersionWarning(root)
1559 if tkversionwarning:
1560 shell.interp.runcommand(''.join(("print('", tkversionwarning, "')")))
1561
Terry Jan Reedyeaa7e782012-05-26 20:33:32 -04001562 while flist.inversedict: # keep IDLE running while files are open.
1563 root.mainloop()
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001564 root.destroy()
1565
David Scherer7aced172000-08-15 01:13:23 +00001566if __name__ == "__main__":
Kurt B. Kaiser9e8b8282003-06-15 17:38:45 +00001567 sys.modules['PyShell'] = sys.modules['__main__']
David Scherer7aced172000-08-15 01:13:23 +00001568 main()