blob: 76e92b2d8c2a31fc4dd1121afe6daf96243d57ca [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
18
Kurt B. Kaiser2303b1c2003-11-24 05:26:16 +000019try:
Georg Brandl6634bf22008-05-20 07:13:37 +000020 from Tkinter import *
Kurt B. Kaiser2303b1c2003-11-24 05:26:16 +000021except ImportError:
Georg Brandl6634bf22008-05-20 07:13:37 +000022 print>>sys.__stderr__, "** IDLE can't import Tkinter. " \
Kurt B. Kaiser2303b1c2003-11-24 05:26:16 +000023 "Your Python may not be configured for Tk. **"
24 sys.exit(1)
Georg Brandl6634bf22008-05-20 07:13:37 +000025import tkMessageBox
David Scherer7aced172000-08-15 01:13:23 +000026
Florent Xiclunad630c042010-04-02 07:24:52 +000027from idlelib.EditorWindow import EditorWindow, fixwordbreaks
28from idlelib.FileList import FileList
29from idlelib.ColorDelegator import ColorDelegator
30from idlelib.UndoDelegator import UndoDelegator
31from idlelib.OutputWindow import OutputWindow
32from idlelib.configHandler import idleConf
33from idlelib import idlever
34from idlelib import rpc
35from idlelib import Debugger
36from idlelib import RemoteDebugger
37from idlelib import macosxSupport
Chui Tey5d2af632002-05-26 13:36:41 +000038
Kurt B. Kaiserb9764192002-09-23 04:10:37 +000039IDENTCHARS = string.ascii_letters + string.digits + "_"
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +000040HOST = '127.0.0.1' # python execution server on localhost loopback
41PORT = 0 # someday pass in host, port for remote debug capability
Kurt B. Kaiserb9764192002-09-23 04:10:37 +000042
Kurt B. Kaisera00050f2003-05-08 20:26:55 +000043try:
44 from signal import SIGTERM
45except ImportError:
46 SIGTERM = 15
47
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000048# Override warnings module to write to warning_stream. Initialize to send IDLE
49# internal warnings to the console. ScriptBinding.check_syntax() will
50# temporarily redirect the stream to the shell window to display warnings when
51# checking user's code.
52global warning_stream
53warning_stream = sys.__stderr__
Chui Tey5d2af632002-05-26 13:36:41 +000054try:
55 import warnings
56except ImportError:
57 pass
58else:
Benjamin Petersonb76444b2008-10-16 19:40:14 +000059 def idle_showwarning(message, category, filename, lineno,
60 file=None, line=None):
Guilherme Polof198ac22009-08-14 14:03:07 +000061 if file is None:
62 file = warning_stream
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000063 try:
Guilherme Polof198ac22009-08-14 14:03:07 +000064 file.write(warnings.formatwarning(message, category, filename,
Senthil Kumaran13502b12011-07-03 17:38:53 -070065 lineno, line=line))
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000066 except IOError:
67 pass ## file (probably __stderr__) is invalid, warning dropped.
Chui Tey5d2af632002-05-26 13:36:41 +000068 warnings.showwarning = idle_showwarning
Guilherme Polof198ac22009-08-14 14:03:07 +000069 def idle_formatwarning(message, category, filename, lineno, line=None):
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000070 """Format warnings the IDLE way"""
71 s = "\nWarning (from warnings module):\n"
72 s += ' File \"%s\", line %s\n' % (filename, lineno)
Guilherme Polof198ac22009-08-14 14:03:07 +000073 if line is None:
74 line = linecache.getline(filename, lineno)
75 line = line.strip()
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000076 if line:
77 s += " %s\n" % line
78 s += "%s: %s\n>>> " % (category.__name__, message)
79 return s
80 warnings.formatwarning = idle_formatwarning
Chui Tey5d2af632002-05-26 13:36:41 +000081
Kurt B. Kaiserf7a88992004-11-13 21:05:58 +000082def extended_linecache_checkcache(filename=None,
83 orig_checkcache=linecache.checkcache):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +000084 """Extend linecache.checkcache to preserve the <pyshell#...> entries
85
Kurt B. Kaiserf7a88992004-11-13 21:05:58 +000086 Rather than repeating the linecache code, patch it to save the
87 <pyshell#...> entries, call the original linecache.checkcache()
Guilherme Polof198ac22009-08-14 14:03:07 +000088 (skipping them), and then restore the saved entries.
Kurt B. Kaiserf7a88992004-11-13 21:05:58 +000089
90 orig_checkcache is bound at definition time to the original
91 method, allowing it to be patched.
Kurt B. Kaiser45186c42002-10-23 04:48:08 +000092 """
David Scherer7aced172000-08-15 01:13:23 +000093 cache = linecache.cache
94 save = {}
Guilherme Polof198ac22009-08-14 14:03:07 +000095 for key in list(cache):
96 if key[:1] + key[-1:] == '<>':
97 save[key] = cache.pop(key)
98 orig_checkcache(filename)
David Scherer7aced172000-08-15 01:13:23 +000099 cache.update(save)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000100
Kurt B. Kaiser81885592002-11-29 22:10:53 +0000101# Patch linecache.checkcache():
102linecache.checkcache = extended_linecache_checkcache
David Scherer7aced172000-08-15 01:13:23 +0000103
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000104
David Scherer7aced172000-08-15 01:13:23 +0000105class PyShellEditorWindow(EditorWindow):
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000106 "Regular text edit window in IDLE, supports breakpoints"
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000107
David Scherer7aced172000-08-15 01:13:23 +0000108 def __init__(self, *args):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000109 self.breakpoints = []
Raymond Hettinger931237e2003-07-09 18:48:24 +0000110 EditorWindow.__init__(self, *args)
David Scherer7aced172000-08-15 01:13:23 +0000111 self.text.bind("<<set-breakpoint-here>>", self.set_breakpoint_here)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000112 self.text.bind("<<clear-breakpoint-here>>", self.clear_breakpoint_here)
David Scherer7aced172000-08-15 01:13:23 +0000113 self.text.bind("<<open-python-shell>>", self.flist.open_shell)
114
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000115 self.breakpointPath = os.path.join(idleConf.GetUserCfgDir(),
116 'breakpoints.lst')
Chui Teya2adb0f2002-11-04 22:14:54 +0000117 # whenever a file is changed, restore breakpoints
118 if self.io.filename: self.restore_file_breaks()
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)
124
Andrew Svetlov5018db72012-11-01 22:39:14 +0200125 rmenu_specs = [
126 ("Cut", "<<cut>>", "rmenu_check_cut"),
127 ("Copy", "<<copy>>", "rmenu_check_copy"),
128 ("Paste", "<<paste>>", "rmenu_check_paste"),
129 ("Set Breakpoint", "<<set-breakpoint-here>>", None),
130 ("Clear Breakpoint", "<<clear-breakpoint-here>>", None)
131 ]
David Scherer7aced172000-08-15 01:13:23 +0000132
Chui Teya2adb0f2002-11-04 22:14:54 +0000133 def set_breakpoint(self, lineno):
134 text = self.text
135 filename = self.io.filename
136 text.tag_add("BREAK", "%d.0" % lineno, "%d.0" % (lineno+1))
137 try:
138 i = self.breakpoints.index(lineno)
139 except ValueError: # only add if missing, i.e. do once
140 self.breakpoints.append(lineno)
141 try: # update the subprocess debugger
142 debug = self.flist.pyshell.interp.debugger
143 debug.set_breakpoint_here(filename, lineno)
144 except: # but debugger may not be active right now....
145 pass
146
David Scherer7aced172000-08-15 01:13:23 +0000147 def set_breakpoint_here(self, event=None):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000148 text = self.text
149 filename = self.io.filename
150 if not filename:
151 text.bell()
David Scherer7aced172000-08-15 01:13:23 +0000152 return
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000153 lineno = int(float(text.index("insert")))
Chui Teya2adb0f2002-11-04 22:14:54 +0000154 self.set_breakpoint(lineno)
David Scherer7aced172000-08-15 01:13:23 +0000155
Kurt B. Kaiser669f4c32002-06-20 04:01:47 +0000156 def clear_breakpoint_here(self, event=None):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000157 text = self.text
158 filename = self.io.filename
159 if not filename:
160 text.bell()
Kurt B. Kaiser669f4c32002-06-20 04:01:47 +0000161 return
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000162 lineno = int(float(text.index("insert")))
163 try:
164 self.breakpoints.remove(lineno)
165 except:
166 pass
167 text.tag_remove("BREAK", "insert linestart",\
168 "insert lineend +1char")
169 try:
170 debug = self.flist.pyshell.interp.debugger
171 debug.clear_breakpoint_here(filename, lineno)
172 except:
173 pass
174
175 def clear_file_breaks(self):
176 if self.breakpoints:
177 text = self.text
178 filename = self.io.filename
179 if not filename:
180 text.bell()
181 return
182 self.breakpoints = []
183 text.tag_remove("BREAK", "1.0", END)
184 try:
185 debug = self.flist.pyshell.interp.debugger
186 debug.clear_file_breaks(filename)
187 except:
188 pass
189
Chui Teya2adb0f2002-11-04 22:14:54 +0000190 def store_file_breaks(self):
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000191 "Save breakpoints when file is saved"
192 # XXX 13 Dec 2002 KBK Currently the file must be saved before it can
193 # be run. The breaks are saved at that time. If we introduce
194 # a temporary file save feature the save breaks functionality
195 # needs to be re-verified, since the breaks at the time the
196 # temp file is created may differ from the breaks at the last
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000197 # permanent save of the file. Currently, a break introduced
198 # after a save will be effective, but not persistent.
199 # This is necessary to keep the saved breaks synched with the
200 # saved file.
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000201 #
202 # Breakpoints are set as tagged ranges in the text. Certain
203 # kinds of edits cause these ranges to be deleted: Inserting
204 # or deleting a line just before a breakpoint, and certain
205 # deletions prior to a breakpoint. These issues need to be
206 # investigated and understood. It's not clear if they are
207 # Tk issues or IDLE issues, or whether they can actually
208 # be fixed. Since a modified file has to be saved before it is
209 # run, and since self.breakpoints (from which the subprocess
210 # debugger is loaded) is updated during the save, the visible
211 # breaks stay synched with the subprocess even if one of these
212 # unexpected breakpoint deletions occurs.
213 breaks = self.breakpoints
214 filename = self.io.filename
Chui Teya2adb0f2002-11-04 22:14:54 +0000215 try:
Ned Deily40ad0412011-12-14 14:57:43 -0800216 with open(self.breakpointPath,"r") as old_file:
217 lines = old_file.readlines()
Chui Teya2adb0f2002-11-04 22:14:54 +0000218 except IOError:
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000219 lines = []
Ned Deily40ad0412011-12-14 14:57:43 -0800220 try:
221 with open(self.breakpointPath,"w") as new_file:
222 for line in lines:
223 if not line.startswith(filename + '='):
224 new_file.write(line)
225 self.update_breakpoints()
226 breaks = self.breakpoints
227 if breaks:
228 new_file.write(filename + '=' + str(breaks) + '\n')
229 except IOError as err:
230 if not getattr(self.root, "breakpoint_error_displayed", False):
231 self.root.breakpoint_error_displayed = True
232 tkMessageBox.showerror(title='IDLE Error',
233 message='Unable to update breakpoint list:\n%s'
234 % str(err),
235 parent=self.text)
Chui Teya2adb0f2002-11-04 22:14:54 +0000236
237 def restore_file_breaks(self):
238 self.text.update() # this enables setting "BREAK" tags to be visible
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000239 filename = self.io.filename
240 if filename is None:
241 return
Chui Tey69371d62002-11-04 23:39:45 +0000242 if os.path.isfile(self.breakpointPath):
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000243 lines = open(self.breakpointPath,"r").readlines()
Chui Tey69371d62002-11-04 23:39:45 +0000244 for line in lines:
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000245 if line.startswith(filename + '='):
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000246 breakpoint_linenumbers = eval(line[len(filename)+1:])
Chui Tey69371d62002-11-04 23:39:45 +0000247 for breakpoint_linenumber in breakpoint_linenumbers:
248 self.set_breakpoint(breakpoint_linenumber)
Chui Teya2adb0f2002-11-04 22:14:54 +0000249
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000250 def update_breakpoints(self):
251 "Retrieves all the breakpoints in the current window"
Chui Teya2adb0f2002-11-04 22:14:54 +0000252 text = self.text
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000253 ranges = text.tag_ranges("BREAK")
254 linenumber_list = self.ranges_to_linenumbers(ranges)
255 self.breakpoints = linenumber_list
256
257 def ranges_to_linenumbers(self, ranges):
258 lines = []
259 for index in range(0, len(ranges), 2):
Andrew Svetlov8a15c372012-07-31 19:51:27 +0300260 lineno = int(float(ranges[index].string))
261 end = int(float(ranges[index+1].string))
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000262 while lineno < end:
263 lines.append(lineno)
264 lineno += 1
265 return lines
266
Kurt B. Kaiser11220fa2002-12-24 00:57:22 +0000267# XXX 13 Dec 2002 KBK Not used currently
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000268# def saved_change_hook(self):
269# "Extend base method - clear breaks if module is modified"
270# if not self.get_saved():
271# self.clear_file_breaks()
272# EditorWindow.saved_change_hook(self)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000273
274 def _close(self):
275 "Extend base method - clear breaks when module is closed"
276 self.clear_file_breaks()
277 EditorWindow._close(self)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000278
David Scherer7aced172000-08-15 01:13:23 +0000279
280class PyShellFileList(FileList):
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000281 "Extend base class: IDLE supports a shell and breakpoints"
David Scherer7aced172000-08-15 01:13:23 +0000282
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000283 # override FileList's class variable, instances return PyShellEditorWindow
284 # instead of EditorWindow when new edit windows are created.
David Scherer7aced172000-08-15 01:13:23 +0000285 EditorWindow = PyShellEditorWindow
286
287 pyshell = None
288
289 def open_shell(self, event=None):
290 if self.pyshell:
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000291 self.pyshell.top.wakeup()
David Scherer7aced172000-08-15 01:13:23 +0000292 else:
293 self.pyshell = PyShell(self)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000294 if self.pyshell:
295 if not self.pyshell.begin():
296 return None
David Scherer7aced172000-08-15 01:13:23 +0000297 return self.pyshell
298
299
300class ModifiedColorDelegator(ColorDelegator):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000301 "Extend base class: colorizer for the shell window itself"
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000302
Steven M. Gavab77d3432002-03-02 07:16:21 +0000303 def __init__(self):
304 ColorDelegator.__init__(self)
305 self.LoadTagDefs()
David Scherer7aced172000-08-15 01:13:23 +0000306
307 def recolorize_main(self):
308 self.tag_remove("TODO", "1.0", "iomark")
309 self.tag_add("SYNC", "1.0", "iomark")
310 ColorDelegator.recolorize_main(self)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000311
Steven M. Gavab77d3432002-03-02 07:16:21 +0000312 def LoadTagDefs(self):
313 ColorDelegator.LoadTagDefs(self)
314 theme = idleConf.GetOption('main','Theme','name')
315 self.tagdefs.update({
316 "stdin": {'background':None,'foreground':None},
317 "stdout": idleConf.GetHighlight(theme, "stdout"),
318 "stderr": idleConf.GetHighlight(theme, "stderr"),
319 "console": idleConf.GetHighlight(theme, "console"),
Steven M. Gavab77d3432002-03-02 07:16:21 +0000320 })
David Scherer7aced172000-08-15 01:13:23 +0000321
Ned Deily5e247b72012-05-31 09:17:29 -0700322 def removecolors(self):
323 # Don't remove shell color tags before "iomark"
324 for tag in self.tagdefs:
325 self.tag_remove(tag, "iomark", "end")
326
David Scherer7aced172000-08-15 01:13:23 +0000327class ModifiedUndoDelegator(UndoDelegator):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000328 "Extend base class: forbid insert/delete before the I/O mark"
David Scherer7aced172000-08-15 01:13:23 +0000329
330 def insert(self, index, chars, tags=None):
331 try:
332 if self.delegate.compare(index, "<", "iomark"):
333 self.delegate.bell()
334 return
335 except TclError:
336 pass
337 UndoDelegator.insert(self, index, chars, tags)
338
339 def delete(self, index1, index2=None):
340 try:
341 if self.delegate.compare(index1, "<", "iomark"):
342 self.delegate.bell()
343 return
344 except TclError:
345 pass
346 UndoDelegator.delete(self, index1, index2)
347
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000348
349class MyRPCClient(rpc.RPCClient):
350
351 def handle_EOF(self):
352 "Override the base class - just re-raise EOFError"
353 raise EOFError
354
Kurt B. Kaiser8d1f11b2003-05-26 22:20:34 +0000355
David Scherer7aced172000-08-15 01:13:23 +0000356class ModifiedInterpreter(InteractiveInterpreter):
357
358 def __init__(self, tkconsole):
359 self.tkconsole = tkconsole
360 locals = sys.modules['__main__'].__dict__
361 InteractiveInterpreter.__init__(self, locals=locals)
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000362 self.save_warnings_filters = None
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000363 self.restarting = False
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +0000364 self.subprocess_arglist = None
365 self.port = PORT
Ned Deily86d669b2011-10-30 19:58:04 -0700366 self.original_compiler_flags = self.compile.compiler.flags
David Scherer7aced172000-08-15 01:13:23 +0000367
Chui Tey5d2af632002-05-26 13:36:41 +0000368 rpcclt = None
369 rpcpid = None
370
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000371 def spawn_subprocess(self):
Florent Xiclunac8a730b2010-03-25 20:32:07 +0000372 if self.subprocess_arglist is None:
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +0000373 self.subprocess_arglist = self.build_subprocess_arglist()
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000374 args = self.subprocess_arglist
Kurt B. Kaiserb7855182003-08-14 14:54:28 +0000375 self.rpcpid = os.spawnv(os.P_NOWAIT, sys.executable, args)
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000376
Tony Lowndsf53dec22002-12-20 04:24:43 +0000377 def build_subprocess_arglist(self):
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +0000378 assert (self.port!=0), (
379 "Socket should have been assigned a port number.")
Tony Lownds2398d572003-05-13 15:28:21 +0000380 w = ['-W' + s for s in sys.warnoptions]
Georg Brandld0761532006-10-12 07:57:21 +0000381 if 1/2 > 0: # account for new division
382 w.append('-Qnew')
Tony Lownds2398d572003-05-13 15:28:21 +0000383 # Maybe IDLE is installed and is being accessed via sys.path,
384 # or maybe it's not installed and the idle.py script is being
385 # run from the IDLE source directory.
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000386 del_exitf = idleConf.GetOption('main', 'General', 'delete-exitfunc',
387 default=False, type='bool')
Tony Lownds2398d572003-05-13 15:28:21 +0000388 if __name__ == 'idlelib.PyShell':
Walter Dörwald70a6b492004-02-12 17:35:32 +0000389 command = "__import__('idlelib.run').run.main(%r)" % (del_exitf,)
Tony Lowndsf2324b92002-09-29 00:34:10 +0000390 else:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000391 command = "__import__('run').main(%r)" % (del_exitf,)
Kurt B. Kaiserb7855182003-08-14 14:54:28 +0000392 if sys.platform[:3] == 'win' and ' ' in sys.executable:
393 # handle embedded space in path by quoting the argument
394 decorated_exec = '"%s"' % sys.executable
395 else:
396 decorated_exec = sys.executable
397 return [decorated_exec] + w + ["-c", command, str(self.port)]
Tony Lowndsf2324b92002-09-29 00:34:10 +0000398
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000399 def start_subprocess(self):
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +0000400 addr = (HOST, self.port)
401 # GUI makes several attempts to acquire socket, listens for connection
Kurt B. Kaiser5db48432003-05-15 03:40:51 +0000402 for i in range(3):
Chui Tey5d2af632002-05-26 13:36:41 +0000403 time.sleep(i)
404 try:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000405 self.rpcclt = MyRPCClient(addr)
Chui Tey5d2af632002-05-26 13:36:41 +0000406 break
407 except socket.error, err:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000408 pass
Chui Tey5d2af632002-05-26 13:36:41 +0000409 else:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000410 self.display_port_binding_error()
411 return None
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +0000412 # if PORT was 0, system will assign an 'ephemeral' port. Find it out:
413 self.port = self.rpcclt.listening_sock.getsockname()[1]
414 # if PORT was not 0, probably working with a remote execution server
415 if PORT != 0:
416 # To allow reconnection within the 2MSL wait (cf. Stevens TCP
417 # V1, 18.6), set SO_REUSEADDR. Note that this can be problematic
418 # on Windows since the implementation allows two active sockets on
419 # the same address!
420 self.rpcclt.listening_sock.setsockopt(socket.SOL_SOCKET,
421 socket.SO_REUSEADDR, 1)
422 self.spawn_subprocess()
423 #time.sleep(20) # test to simulate GUI not accepting connection
Kurt B. Kaiserb4179362002-07-26 00:06:42 +0000424 # Accept the connection from the Python execution server
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000425 self.rpcclt.listening_sock.settimeout(10)
426 try:
427 self.rpcclt.accept()
428 except socket.timeout, err:
429 self.display_no_subprocess_error()
430 return None
Serhiy Storchaka9abc8302013-01-25 15:30:35 +0200431 self.rpcclt.register("console", self.tkconsole)
432 self.rpcclt.register("stdin", self.tkconsole.stdin)
Kurt B. Kaiser969de452002-06-12 03:28:57 +0000433 self.rpcclt.register("stdout", self.tkconsole.stdout)
434 self.rpcclt.register("stderr", self.tkconsole.stderr)
Chui Tey5d2af632002-05-26 13:36:41 +0000435 self.rpcclt.register("flist", self.tkconsole.flist)
Kurt B. Kaiser8cd0def2003-01-31 05:06:43 +0000436 self.rpcclt.register("linecache", linecache)
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000437 self.rpcclt.register("interp", self)
Terry Jan Reedyb98000a2012-01-31 02:09:25 -0500438 self.transfer_path(with_cwd=True)
Chui Tey5d2af632002-05-26 13:36:41 +0000439 self.poll_subprocess()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000440 return self.rpcclt
Chui Tey5d2af632002-05-26 13:36:41 +0000441
Terry Jan Reedyb98000a2012-01-31 02:09:25 -0500442 def restart_subprocess(self, with_cwd=False):
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000443 if self.restarting:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000444 return self.rpcclt
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000445 self.restarting = True
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000446 # close only the subprocess debugger
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000447 debug = self.getdebugger()
448 if debug:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000449 try:
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000450 # Only close subprocess debugger, don't unregister gui_adap!
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000451 RemoteDebugger.close_subprocess_debugger(self.rpcclt)
452 except:
453 pass
454 # Kill subprocess, spawn a new one, accept connection.
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000455 self.rpcclt.close()
456 self.unix_terminate()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000457 console = self.tkconsole
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000458 was_executing = console.executing
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000459 console.executing = False
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000460 self.spawn_subprocess()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000461 try:
462 self.rpcclt.accept()
463 except socket.timeout, err:
464 self.display_no_subprocess_error()
465 return None
Terry Jan Reedyb98000a2012-01-31 02:09:25 -0500466 self.transfer_path(with_cwd=with_cwd)
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000467 # annotate restart in shell window and mark it
Kurt B. Kaiser4cc5ef52003-01-22 00:23:23 +0000468 console.text.delete("iomark", "end-1c")
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000469 if was_executing:
470 console.write('\n')
471 console.showprompt()
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000472 halfbar = ((int(console.width) - 16) // 2) * '='
473 console.write(halfbar + ' RESTART ' + halfbar)
474 console.text.mark_set("restart", "end-1c")
475 console.text.mark_gravity("restart", "left")
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000476 console.showprompt()
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000477 # restart subprocess debugger
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000478 if debug:
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000479 # Restarted debugger connects to current instance of debug GUI
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000480 gui = RemoteDebugger.restart_subprocess_debugger(self.rpcclt)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000481 # reload remote debugger breakpoints for all PyShellEditWindows
482 debug.load_breakpoints()
Ned Deily86d669b2011-10-30 19:58:04 -0700483 self.compile.compiler.flags = self.original_compiler_flags
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000484 self.restarting = False
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000485 return self.rpcclt
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000486
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000487 def __request_interrupt(self):
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000488 self.rpcclt.remotecall("exec", "interrupt_the_server", (), {})
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000489
490 def interrupt_subprocess(self):
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000491 threading.Thread(target=self.__request_interrupt).start()
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000492
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000493 def kill_subprocess(self):
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000494 try:
495 self.rpcclt.close()
496 except AttributeError: # no socket
497 pass
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000498 self.unix_terminate()
499 self.tkconsole.executing = False
500 self.rpcclt = None
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000501
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000502 def unix_terminate(self):
503 "UNIX: make sure subprocess is terminated and collect status"
504 if hasattr(os, 'kill'):
505 try:
506 os.kill(self.rpcpid, SIGTERM)
507 except OSError:
508 # process already terminated:
509 return
510 else:
511 try:
512 os.waitpid(self.rpcpid, 0)
513 except OSError:
514 return
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000515
Terry Jan Reedyb98000a2012-01-31 02:09:25 -0500516 def transfer_path(self, with_cwd=False):
517 if with_cwd: # Issue 13506
518 path = [''] # include Current Working Directory
519 path.extend(sys.path)
520 else:
521 path = sys.path
Terry Jan Reedy1d4ae482012-01-31 02:55:32 -0500522
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000523 self.runcommand("""if 1:
524 import sys as _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +0000525 _sys.path = %r
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000526 del _sys
Terry Jan Reedyb98000a2012-01-31 02:09:25 -0500527 \n""" % (path,))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000528
Chui Tey5d2af632002-05-26 13:36:41 +0000529 active_seq = None
530
531 def poll_subprocess(self):
532 clt = self.rpcclt
533 if clt is None:
534 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000535 try:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000536 response = clt.pollresponse(self.active_seq, wait=0.05)
537 except (EOFError, IOError, KeyboardInterrupt):
538 # lost connection or subprocess terminated itself, restart
539 # [the KBI is from rpc.SocketIO.handle_EOF()]
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000540 if self.tkconsole.closing:
541 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000542 response = None
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000543 self.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000544 if response:
545 self.tkconsole.resetoutput()
546 self.active_seq = None
547 how, what = response
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000548 console = self.tkconsole.console
Chui Tey5d2af632002-05-26 13:36:41 +0000549 if how == "OK":
550 if what is not None:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000551 print >>console, repr(what)
Chui Tey5d2af632002-05-26 13:36:41 +0000552 elif how == "EXCEPTION":
Chui Tey5d2af632002-05-26 13:36:41 +0000553 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
554 self.remote_stack_viewer()
555 elif how == "ERROR":
Kurt B. Kaiser0930c432002-12-06 21:45:24 +0000556 errmsg = "PyShell.ModifiedInterpreter: Subprocess ERROR:\n"
557 print >>sys.__stderr__, errmsg, what
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000558 print >>console, errmsg, what
559 # we received a response to the currently active seq number:
Kurt B. Kaiserd112bc72006-08-16 05:01:42 +0000560 try:
561 self.tkconsole.endexecuting()
562 except AttributeError: # shell may have closed
563 pass
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000564 # Reschedule myself
565 if not self.tkconsole.closing:
566 self.tkconsole.text.after(self.tkconsole.pollinterval,
567 self.poll_subprocess)
Chui Tey5d2af632002-05-26 13:36:41 +0000568
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000569 debugger = None
570
571 def setdebugger(self, debugger):
572 self.debugger = debugger
573
574 def getdebugger(self):
575 return self.debugger
576
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000577 def open_remote_stack_viewer(self):
578 """Initiate the remote stack viewer from a separate thread.
579
580 This method is called from the subprocess, and by returning from this
581 method we allow the subprocess to unblock. After a bit the shell
582 requests the subprocess to open the remote stack viewer which returns a
Ezio Melottic569cfe2010-07-23 16:55:21 +0000583 static object looking at the last exception. It is queried through
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000584 the RPC mechanism.
585
586 """
587 self.tkconsole.text.after(300, self.remote_stack_viewer)
588 return
589
Chui Tey5d2af632002-05-26 13:36:41 +0000590 def remote_stack_viewer(self):
Florent Xiclunad630c042010-04-02 07:24:52 +0000591 from idlelib import RemoteObjectBrowser
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000592 oid = self.rpcclt.remotequeue("exec", "stackviewer", ("flist",), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000593 if oid is None:
594 self.tkconsole.root.bell()
595 return
596 item = RemoteObjectBrowser.StubObjectTreeItem(self.rpcclt, oid)
Florent Xiclunad630c042010-04-02 07:24:52 +0000597 from idlelib.TreeWidget import ScrolledCanvas, TreeNode
Chui Tey5d2af632002-05-26 13:36:41 +0000598 top = Toplevel(self.tkconsole.root)
Kurt B. Kaiser73360a32004-03-08 18:15:31 +0000599 theme = idleConf.GetOption('main','Theme','name')
600 background = idleConf.GetHighlight(theme, 'normal')['background']
601 sc = ScrolledCanvas(top, bg=background, highlightthickness=0)
Chui Tey5d2af632002-05-26 13:36:41 +0000602 sc.frame.pack(expand=1, fill="both")
603 node = TreeNode(sc.canvas, None, item)
604 node.expand()
605 # XXX Should GC the remote tree when closing the window
606
David Scherer7aced172000-08-15 01:13:23 +0000607 gid = 0
608
609 def execsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000610 "Like runsource() but assumes complete exec source"
David Scherer7aced172000-08-15 01:13:23 +0000611 filename = self.stuffsource(source)
612 self.execfile(filename, source)
613
614 def execfile(self, filename, source=None):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000615 "Execute an existing file"
David Scherer7aced172000-08-15 01:13:23 +0000616 if source is None:
617 source = open(filename, "r").read()
618 try:
619 code = compile(source, filename, "exec")
620 except (OverflowError, SyntaxError):
621 self.tkconsole.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000622 tkerr = self.tkconsole.stderr
623 print>>tkerr, '*** Error in script or command!\n'
624 print>>tkerr, 'Traceback (most recent call last):'
David Scherer7aced172000-08-15 01:13:23 +0000625 InteractiveInterpreter.showsyntaxerror(self, filename)
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000626 self.tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000627 else:
628 self.runcode(code)
629
630 def runsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000631 "Extend base class method: Stuff the source in the line cache first"
David Scherer7aced172000-08-15 01:13:23 +0000632 filename = self.stuffsource(source)
633 self.more = 0
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000634 self.save_warnings_filters = warnings.filters[:]
635 warnings.filterwarnings(action="error", category=SyntaxWarning)
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000636 if isinstance(source, types.UnicodeType):
Florent Xiclunad630c042010-04-02 07:24:52 +0000637 from idlelib import IOBinding
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000638 try:
639 source = source.encode(IOBinding.encoding)
640 except UnicodeError:
641 self.tkconsole.resetoutput()
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +0000642 self.write("Unsupported characters in input\n")
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000643 return
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000644 try:
Kurt B. Kaiser935ea9a2005-05-10 03:44:24 +0000645 # InteractiveInterpreter.runsource() calls its runcode() method,
646 # which is overridden (see below)
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000647 return InteractiveInterpreter.runsource(self, source, filename)
648 finally:
649 if self.save_warnings_filters is not None:
650 warnings.filters[:] = self.save_warnings_filters
651 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000652
653 def stuffsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000654 "Stuff source in the filename cache"
David Scherer7aced172000-08-15 01:13:23 +0000655 filename = "<pyshell#%d>" % self.gid
656 self.gid = self.gid + 1
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000657 lines = source.split("\n")
David Scherer7aced172000-08-15 01:13:23 +0000658 linecache.cache[filename] = len(source)+1, 0, lines, filename
659 return filename
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000660
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000661 def prepend_syspath(self, filename):
662 "Prepend sys.path with file's directory if not already included"
663 self.runcommand("""if 1:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000664 _filename = %r
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000665 import sys as _sys
666 from os.path import dirname as _dirname
667 _dir = _dirname(_filename)
668 if not _dir in _sys.path:
669 _sys.path.insert(0, _dir)
670 del _filename, _sys, _dirname, _dir
Walter Dörwald70a6b492004-02-12 17:35:32 +0000671 \n""" % (filename,))
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000672
David Scherer7aced172000-08-15 01:13:23 +0000673 def showsyntaxerror(self, filename=None):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000674 """Extend base class method: Add Colorizing
675
676 Color the offending position instead of printing it and pointing at it
677 with a caret.
678
679 """
David Scherer7aced172000-08-15 01:13:23 +0000680 text = self.tkconsole.text
681 stuff = self.unpackerror()
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000682 if stuff:
683 msg, lineno, offset, line = stuff
684 if lineno == 1:
685 pos = "iomark + %d chars" % (offset-1)
686 else:
687 pos = "iomark linestart + %d lines + %d chars" % \
688 (lineno-1, offset-1)
689 text.tag_add("ERROR", pos)
690 text.see(pos)
691 char = text.get(pos)
692 if char and char in IDENTCHARS:
693 text.tag_add("ERROR", pos + " wordstart", pos)
694 self.tkconsole.resetoutput()
695 self.write("SyntaxError: %s\n" % str(msg))
696 else:
David Scherer7aced172000-08-15 01:13:23 +0000697 self.tkconsole.resetoutput()
698 InteractiveInterpreter.showsyntaxerror(self, filename)
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000699 self.tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000700
701 def unpackerror(self):
702 type, value, tb = sys.exc_info()
703 ok = type is SyntaxError
704 if ok:
705 try:
706 msg, (dummy_filename, lineno, offset, line) = value
Kurt B. Kaiserbea57c62003-07-09 04:27:24 +0000707 if not offset:
708 offset = 0
David Scherer7aced172000-08-15 01:13:23 +0000709 except:
710 ok = 0
711 if ok:
712 return msg, lineno, offset, line
713 else:
714 return None
715
716 def showtraceback(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000717 "Extend base class method to reset output properly"
David Scherer7aced172000-08-15 01:13:23 +0000718 self.tkconsole.resetoutput()
719 self.checklinecache()
720 InteractiveInterpreter.showtraceback(self)
Chui Tey5d2af632002-05-26 13:36:41 +0000721 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
722 self.tkconsole.open_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +0000723
724 def checklinecache(self):
725 c = linecache.cache
726 for key in c.keys():
727 if key[:1] + key[-1:] != "<>":
728 del c[key]
729
Chui Tey5d2af632002-05-26 13:36:41 +0000730 def runcommand(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000731 "Run the code without invoking the debugger"
Chui Tey5d2af632002-05-26 13:36:41 +0000732 # The code better not raise an exception!
733 if self.tkconsole.executing:
Neal Norwitzf4c4f112002-11-30 18:49:10 +0000734 self.display_executing_dialog()
Chui Tey5d2af632002-05-26 13:36:41 +0000735 return 0
736 if self.rpcclt:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000737 self.rpcclt.remotequeue("exec", "runcode", (code,), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000738 else:
739 exec code in self.locals
740 return 1
741
David Scherer7aced172000-08-15 01:13:23 +0000742 def runcode(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000743 "Override base class method"
Chui Tey5d2af632002-05-26 13:36:41 +0000744 if self.tkconsole.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000745 self.interp.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000746 self.checklinecache()
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000747 if self.save_warnings_filters is not None:
748 warnings.filters[:] = self.save_warnings_filters
749 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000750 debugger = self.debugger
751 try:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000752 self.tkconsole.beginexecuting()
Kurt B. Kaiserdddeb0e2007-02-06 03:21:40 +0000753 if not debugger and self.rpcclt is not None:
754 self.active_seq = self.rpcclt.asyncqueue("exec", "runcode",
755 (code,), {})
756 elif debugger:
757 debugger.run(code, self.locals)
758 else:
759 exec code in self.locals
760 except SystemExit:
761 if not self.tkconsole.closing:
762 if tkMessageBox.askyesno(
763 "Exit?",
764 "Do you want to exit altogether?",
765 default="yes",
766 master=self.tkconsole.text):
Kurt B. Kaiserf137e1d2006-08-16 07:04:17 +0000767 raise
Kurt B. Kaiserdddeb0e2007-02-06 03:21:40 +0000768 else:
769 self.showtraceback()
770 else:
771 raise
772 except:
773 if use_subprocess:
774 print >>self.tkconsole.stderr, \
775 "IDLE internal error in runcode()"
David Scherer7aced172000-08-15 01:13:23 +0000776 self.showtraceback()
Kurt B. Kaiserdddeb0e2007-02-06 03:21:40 +0000777 self.tkconsole.endexecuting()
778 else:
779 if self.tkconsole.canceled:
780 self.tkconsole.canceled = False
781 print >>self.tkconsole.stderr, "KeyboardInterrupt"
782 else:
783 self.showtraceback()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000784 finally:
785 if not use_subprocess:
Kurt B. Kaiserd112bc72006-08-16 05:01:42 +0000786 try:
787 self.tkconsole.endexecuting()
788 except AttributeError: # shell may have closed
789 pass
David Scherer7aced172000-08-15 01:13:23 +0000790
791 def write(self, s):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000792 "Override base class method"
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000793 self.tkconsole.stderr.write(s)
David Scherer7aced172000-08-15 01:13:23 +0000794
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000795 def display_port_binding_error(self):
796 tkMessageBox.showerror(
797 "Port Binding Error",
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +0000798 "IDLE can't bind to a TCP/IP port, which is necessary to "
799 "communicate with its Python execution server. This might be "
800 "because no networking is installed on this computer. "
801 "Run IDLE with the -n command line switch to start without a "
802 "subprocess and refer to Help/IDLE Help 'Running without a "
803 "subprocess' for further details.",
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000804 master=self.tkconsole.text)
805
806 def display_no_subprocess_error(self):
807 tkMessageBox.showerror(
808 "Subprocess Startup Error",
809 "IDLE's subprocess didn't make connection. Either IDLE can't "
810 "start a subprocess or personal firewall software is blocking "
811 "the connection.",
812 master=self.tkconsole.text)
813
814 def display_executing_dialog(self):
815 tkMessageBox.showerror(
816 "Already executing",
817 "The Python Shell window is already executing a command; "
818 "please wait until it is finished.",
819 master=self.tkconsole.text)
820
821
David Scherer7aced172000-08-15 01:13:23 +0000822class PyShell(OutputWindow):
823
824 shell_title = "Python Shell"
825
826 # Override classes
827 ColorDelegator = ModifiedColorDelegator
828 UndoDelegator = ModifiedUndoDelegator
829
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000830 # Override menus
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000831 menu_specs = [
832 ("file", "_File"),
833 ("edit", "_Edit"),
Kurt B. Kaiser4cc5ef52003-01-22 00:23:23 +0000834 ("debug", "_Debug"),
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000835 ("options", "_Options"),
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000836 ("windows", "_Windows"),
837 ("help", "_Help"),
838 ]
David Scherer7aced172000-08-15 01:13:23 +0000839
Ronald Oussoren19302d92006-06-11 14:33:36 +0000840 if macosxSupport.runningAsOSXApp():
841 del menu_specs[-3]
842 menu_specs[-2] = ("windows", "_Window")
843
844
David Scherer7aced172000-08-15 01:13:23 +0000845 # New classes
Florent Xiclunad630c042010-04-02 07:24:52 +0000846 from idlelib.IdleHistory import History
David Scherer7aced172000-08-15 01:13:23 +0000847
848 def __init__(self, flist=None):
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000849 if use_subprocess:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000850 ms = self.menu_specs
851 if ms[2][0] != "shell":
Kurt B. Kaiser7ae35482006-08-16 21:45:59 +0000852 ms.insert(2, ("shell", "She_ll"))
David Scherer7aced172000-08-15 01:13:23 +0000853 self.interp = ModifiedInterpreter(self)
854 if flist is None:
855 root = Tk()
856 fixwordbreaks(root)
857 root.withdraw()
858 flist = PyShellFileList(root)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000859 #
David Scherer7aced172000-08-15 01:13:23 +0000860 OutputWindow.__init__(self, flist, None, None)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000861 #
Kurt B. Kaiser6af44982005-01-19 00:22:59 +0000862## self.config(usetabs=1, indentwidth=8, context_use_ps1=1)
863 self.usetabs = True
864 # indentwidth must be 8 when using tabs. See note in EditorWindow:
865 self.indentwidth = 8
866 self.context_use_ps1 = True
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000867 #
David Scherer7aced172000-08-15 01:13:23 +0000868 text = self.text
869 text.configure(wrap="char")
870 text.bind("<<newline-and-indent>>", self.enter_callback)
871 text.bind("<<plain-newline-and-indent>>", self.linefeed_callback)
872 text.bind("<<interrupt-execution>>", self.cancel_callback)
David Scherer7aced172000-08-15 01:13:23 +0000873 text.bind("<<end-of-file>>", self.eof_callback)
874 text.bind("<<open-stack-viewer>>", self.open_stack_viewer)
Kurt B. Kaiser57bfe5d2003-05-10 00:09:52 +0000875 text.bind("<<toggle-debugger>>", self.toggle_debugger)
David Scherer7aced172000-08-15 01:13:23 +0000876 text.bind("<<toggle-jit-stack-viewer>>", self.toggle_jit_stack_viewer)
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000877 if use_subprocess:
878 text.bind("<<view-restart>>", self.view_restart_mark)
879 text.bind("<<restart-shell>>", self.restart_shell)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000880 #
David Scherer7aced172000-08-15 01:13:23 +0000881 self.save_stdout = sys.stdout
882 self.save_stderr = sys.stderr
883 self.save_stdin = sys.stdin
Florent Xiclunad630c042010-04-02 07:24:52 +0000884 from idlelib import IOBinding
Serhiy Storchaka9abc8302013-01-25 15:30:35 +0200885 self.stdin = PseudoInputFile(self, "stdin", IOBinding.encoding)
886 self.stdout = PseudoOutputFile(self, "stdout", IOBinding.encoding)
887 self.stderr = PseudoOutputFile(self, "stderr", IOBinding.encoding)
888 self.console = PseudoOutputFile(self, "console", IOBinding.encoding)
Chui Tey5d2af632002-05-26 13:36:41 +0000889 if not use_subprocess:
890 sys.stdout = self.stdout
891 sys.stderr = self.stderr
Martin v. Löwise2b56242012-07-25 10:56:22 +0200892 sys.stdin = self.stdin
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000893 #
David Scherer7aced172000-08-15 01:13:23 +0000894 self.history = self.History(self.text)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000895 #
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000896 self.pollinterval = 50 # millisec
Chui Tey5d2af632002-05-26 13:36:41 +0000897
Kurt B. Kaiser4d5bc602004-06-06 01:29:22 +0000898 def get_standard_extension_names(self):
899 return idleConf.GetExtensions(shell_only=True)
900
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000901 reading = False
902 executing = False
903 canceled = False
904 endoffile = False
905 closing = False
David Scherer7aced172000-08-15 01:13:23 +0000906
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +0000907 def set_warning_stream(self, stream):
Skip Montanarod9161422004-07-06 21:53:27 +0000908 global warning_stream
909 warning_stream = stream
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +0000910
911 def get_warning_stream(self):
912 return warning_stream
913
David Scherer7aced172000-08-15 01:13:23 +0000914 def toggle_debugger(self, event=None):
915 if self.executing:
916 tkMessageBox.showerror("Don't debug now",
917 "You can only toggle the debugger when idle",
918 master=self.text)
919 self.set_debugger_indicator()
920 return "break"
921 else:
922 db = self.interp.getdebugger()
923 if db:
924 self.close_debugger()
925 else:
926 self.open_debugger()
927
928 def set_debugger_indicator(self):
929 db = self.interp.getdebugger()
930 self.setvar("<<toggle-debugger>>", not not db)
931
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000932 def toggle_jit_stack_viewer(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +0000933 pass # All we need is the variable
934
935 def close_debugger(self):
936 db = self.interp.getdebugger()
937 if db:
938 self.interp.setdebugger(None)
939 db.close()
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000940 if self.interp.rpcclt:
941 RemoteDebugger.close_remote_debugger(self.interp.rpcclt)
David Scherer7aced172000-08-15 01:13:23 +0000942 self.resetoutput()
943 self.console.write("[DEBUG OFF]\n")
944 sys.ps1 = ">>> "
945 self.showprompt()
946 self.set_debugger_indicator()
947
948 def open_debugger(self):
Chui Tey5d2af632002-05-26 13:36:41 +0000949 if self.interp.rpcclt:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000950 dbg_gui = RemoteDebugger.start_remote_debugger(self.interp.rpcclt,
951 self)
952 else:
953 dbg_gui = Debugger.Debugger(self)
954 self.interp.setdebugger(dbg_gui)
955 dbg_gui.load_breakpoints()
Chui Tey5d2af632002-05-26 13:36:41 +0000956 sys.ps1 = "[DEBUG ON]\n>>> "
957 self.showprompt()
958 self.set_debugger_indicator()
959
David Scherer7aced172000-08-15 01:13:23 +0000960 def beginexecuting(self):
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000961 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +0000962 self.resetoutput()
963 self.executing = 1
David Scherer7aced172000-08-15 01:13:23 +0000964
965 def endexecuting(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000966 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +0000967 self.executing = 0
968 self.canceled = 0
Chui Tey5d2af632002-05-26 13:36:41 +0000969 self.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000970
971 def close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000972 "Extend EditorWindow.close()"
David Scherer7aced172000-08-15 01:13:23 +0000973 if self.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000974 response = tkMessageBox.askokcancel(
David Scherer7aced172000-08-15 01:13:23 +0000975 "Kill?",
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000976 "The program is still running!\n Do you want to kill it?",
David Scherer7aced172000-08-15 01:13:23 +0000977 default="ok",
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000978 parent=self.text)
Benjamin Peterson5b63acd2008-03-29 15:24:25 +0000979 if response is False:
David Scherer7aced172000-08-15 01:13:23 +0000980 return "cancel"
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +0000981 if self.reading:
982 self.top.quit()
983 self.canceled = True
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000984 self.closing = True
985 # Wait for poll_subprocess() rescheduling to stop
986 self.text.after(2 * self.pollinterval, self.close2)
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000987
988 def close2(self):
989 return EditorWindow.close(self)
David Scherer7aced172000-08-15 01:13:23 +0000990
991 def _close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000992 "Extend EditorWindow._close(), shut down debugger and execution server"
David Scherer7aced172000-08-15 01:13:23 +0000993 self.close_debugger()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000994 if use_subprocess:
995 self.interp.kill_subprocess()
David Scherer7aced172000-08-15 01:13:23 +0000996 # Restore std streams
997 sys.stdout = self.save_stdout
998 sys.stderr = self.save_stderr
999 sys.stdin = self.save_stdin
1000 # Break cycles
1001 self.interp = None
1002 self.console = None
David Scherer7aced172000-08-15 01:13:23 +00001003 self.flist.pyshell = None
1004 self.history = None
Kurt B. Kaiser83118c62002-06-24 17:03:37 +00001005 EditorWindow._close(self)
David Scherer7aced172000-08-15 01:13:23 +00001006
1007 def ispythonsource(self, filename):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +00001008 "Override EditorWindow method: never remove the colorizer"
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001009 return True
David Scherer7aced172000-08-15 01:13:23 +00001010
1011 def short_title(self):
1012 return self.shell_title
1013
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +00001014 COPYRIGHT = \
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001015 'Type "copyright", "credits" or "license()" for more information.'
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +00001016
David Scherer7aced172000-08-15 01:13:23 +00001017 def begin(self):
1018 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001019 if use_subprocess:
1020 nosub = ''
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001021 client = self.interp.start_subprocess()
1022 if not client:
1023 self.close()
Kurt B. Kaiser76637292004-01-21 22:10:01 +00001024 return False
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001025 else:
1026 nosub = "==== No Subprocess ===="
Raymond Hettingerbf3f69e2009-01-26 23:29:09 +00001027 self.write("Python %s on %s\n%s\n%s" %
1028 (sys.version, sys.platform, self.COPYRIGHT, nosub))
David Scherer7aced172000-08-15 01:13:23 +00001029 self.showprompt()
Georg Brandl6634bf22008-05-20 07:13:37 +00001030 import Tkinter
1031 Tkinter._default_root = None # 03Jan04 KBK What's this?
Kurt B. Kaiser76637292004-01-21 22:10:01 +00001032 return True
David Scherer7aced172000-08-15 01:13:23 +00001033
1034 def readline(self):
1035 save = self.reading
1036 try:
1037 self.reading = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001038 self.top.mainloop() # nested mainloop()
David Scherer7aced172000-08-15 01:13:23 +00001039 finally:
1040 self.reading = save
1041 line = self.text.get("iomark", "end-1c")
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001042 if len(line) == 0: # may be EOF if we quit our mainloop with Ctrl-C
1043 line = "\n"
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001044 if isinstance(line, unicode):
Florent Xiclunad630c042010-04-02 07:24:52 +00001045 from idlelib import IOBinding
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001046 try:
1047 line = line.encode(IOBinding.encoding)
1048 except UnicodeError:
1049 pass
David Scherer7aced172000-08-15 01:13:23 +00001050 self.resetoutput()
1051 if self.canceled:
1052 self.canceled = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001053 if not use_subprocess:
1054 raise KeyboardInterrupt
David Scherer7aced172000-08-15 01:13:23 +00001055 if self.endoffile:
1056 self.endoffile = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001057 line = ""
David Scherer7aced172000-08-15 01:13:23 +00001058 return line
1059
1060 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001061 return True
David Scherer7aced172000-08-15 01:13:23 +00001062
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001063 def cancel_callback(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +00001064 try:
1065 if self.text.compare("sel.first", "!=", "sel.last"):
1066 return # Active selection -- always use default binding
1067 except:
1068 pass
1069 if not (self.executing or self.reading):
1070 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001071 self.interp.write("KeyboardInterrupt\n")
David Scherer7aced172000-08-15 01:13:23 +00001072 self.showprompt()
1073 return "break"
1074 self.endoffile = 0
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001075 self.canceled = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001076 if (self.executing and self.interp.rpcclt):
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +00001077 if self.interp.getdebugger():
1078 self.interp.restart_subprocess()
1079 else:
1080 self.interp.interrupt_subprocess()
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001081 if self.reading:
1082 self.top.quit() # exit the nested mainloop() in readline()
David Scherer7aced172000-08-15 01:13:23 +00001083 return "break"
1084
1085 def eof_callback(self, event):
1086 if self.executing and not self.reading:
1087 return # Let the default binding (delete next char) take over
1088 if not (self.text.compare("iomark", "==", "insert") and
1089 self.text.compare("insert", "==", "end-1c")):
1090 return # Let the default binding (delete next char) take over
1091 if not self.executing:
David Scherer7aced172000-08-15 01:13:23 +00001092 self.resetoutput()
1093 self.close()
1094 else:
1095 self.canceled = 0
1096 self.endoffile = 1
1097 self.top.quit()
1098 return "break"
1099
David Scherer7aced172000-08-15 01:13:23 +00001100 def linefeed_callback(self, event):
1101 # Insert a linefeed without entering anything (still autoindented)
1102 if self.reading:
1103 self.text.insert("insert", "\n")
1104 self.text.see("insert")
1105 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001106 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001107 return "break"
1108
1109 def enter_callback(self, event):
1110 if self.executing and not self.reading:
1111 return # Let the default binding (insert '\n') take over
1112 # If some text is selected, recall the selection
1113 # (but only if this before the I/O mark)
1114 try:
1115 sel = self.text.get("sel.first", "sel.last")
1116 if sel:
1117 if self.text.compare("sel.last", "<=", "iomark"):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001118 self.recall(sel, event)
David Scherer7aced172000-08-15 01:13:23 +00001119 return "break"
1120 except:
1121 pass
1122 # If we're strictly before the line containing iomark, recall
1123 # the current line, less a leading prompt, less leading or
1124 # trailing whitespace
1125 if self.text.compare("insert", "<", "iomark linestart"):
1126 # Check if there's a relevant stdin range -- if so, use it
1127 prev = self.text.tag_prevrange("stdin", "insert")
1128 if prev and self.text.compare("insert", "<", prev[1]):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001129 self.recall(self.text.get(prev[0], prev[1]), event)
David Scherer7aced172000-08-15 01:13:23 +00001130 return "break"
1131 next = self.text.tag_nextrange("stdin", "insert")
1132 if next and self.text.compare("insert lineend", ">=", next[0]):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001133 self.recall(self.text.get(next[0], next[1]), event)
David Scherer7aced172000-08-15 01:13:23 +00001134 return "break"
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001135 # No stdin mark -- just get the current line, less any prompt
Kurt B. Kaiserb1754452005-11-18 22:05:48 +00001136 indices = self.text.tag_nextrange("console", "insert linestart")
1137 if indices and \
1138 self.text.compare(indices[0], "<=", "insert linestart"):
1139 self.recall(self.text.get(indices[1], "insert lineend"), event)
1140 else:
1141 self.recall(self.text.get("insert linestart", "insert lineend"), event)
David Scherer7aced172000-08-15 01:13:23 +00001142 return "break"
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001143 # If we're between the beginning of the line and the iomark, i.e.
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001144 # in the prompt area, move to the end of the prompt
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001145 if self.text.compare("insert", "<", "iomark"):
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001146 self.text.mark_set("insert", "iomark")
David Scherer7aced172000-08-15 01:13:23 +00001147 # If we're in the current input and there's only whitespace
1148 # beyond the cursor, erase that whitespace first
1149 s = self.text.get("insert", "end-1c")
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001150 if s and not s.strip():
David Scherer7aced172000-08-15 01:13:23 +00001151 self.text.delete("insert", "end-1c")
1152 # If we're in the current input before its last line,
1153 # insert a newline right at the insert point
1154 if self.text.compare("insert", "<", "end-1c linestart"):
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001155 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001156 return "break"
1157 # We're in the last line; append a newline and submit it
1158 self.text.mark_set("insert", "end-1c")
1159 if self.reading:
1160 self.text.insert("insert", "\n")
1161 self.text.see("insert")
1162 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001163 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001164 self.text.tag_add("stdin", "iomark", "end-1c")
1165 self.text.update_idletasks()
1166 if self.reading:
1167 self.top.quit() # Break out of recursive mainloop() in raw_input()
1168 else:
1169 self.runit()
1170 return "break"
1171
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001172 def recall(self, s, event):
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001173 # remove leading and trailing empty or whitespace lines
1174 s = re.sub(r'^\s*\n', '' , s)
1175 s = re.sub(r'\n\s*$', '', s)
1176 lines = s.split('\n')
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001177 self.text.undo_block_start()
1178 try:
1179 self.text.tag_remove("sel", "1.0", "end")
1180 self.text.mark_set("insert", "end-1c")
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001181 prefix = self.text.get("insert linestart", "insert")
1182 if prefix.rstrip().endswith(':'):
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001183 self.newline_and_indent_event(event)
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001184 prefix = self.text.get("insert linestart", "insert")
1185 self.text.insert("insert", lines[0].strip())
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001186 if len(lines) > 1:
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001187 orig_base_indent = re.search(r'^([ \t]*)', lines[0]).group(0)
1188 new_base_indent = re.search(r'^([ \t]*)', prefix).group(0)
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001189 for line in lines[1:]:
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001190 if line.startswith(orig_base_indent):
1191 # replace orig base indentation with new indentation
1192 line = new_base_indent + line[len(orig_base_indent):]
1193 self.text.insert('insert', '\n'+line.rstrip())
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001194 finally:
1195 self.text.see("insert")
1196 self.text.undo_block_stop()
David Scherer7aced172000-08-15 01:13:23 +00001197
1198 def runit(self):
1199 line = self.text.get("iomark", "end-1c")
1200 # Strip off last newline and surrounding whitespace.
1201 # (To allow you to hit return twice to end a statement.)
1202 i = len(line)
1203 while i > 0 and line[i-1] in " \t":
1204 i = i-1
1205 if i > 0 and line[i-1] == "\n":
1206 i = i-1
1207 while i > 0 and line[i-1] in " \t":
1208 i = i-1
1209 line = line[:i]
1210 more = self.interp.runsource(line)
David Scherer7aced172000-08-15 01:13:23 +00001211
David Scherer7aced172000-08-15 01:13:23 +00001212 def open_stack_viewer(self, event=None):
Chui Tey5d2af632002-05-26 13:36:41 +00001213 if self.interp.rpcclt:
1214 return self.interp.remote_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +00001215 try:
1216 sys.last_traceback
1217 except:
1218 tkMessageBox.showerror("No stack trace",
1219 "There is no stack trace yet.\n"
1220 "(sys.last_traceback is not defined)",
1221 master=self.text)
1222 return
Florent Xiclunad630c042010-04-02 07:24:52 +00001223 from idlelib.StackViewer import StackBrowser
David Scherer7aced172000-08-15 01:13:23 +00001224 sv = StackBrowser(self.root, self.flist)
1225
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001226 def view_restart_mark(self, event=None):
1227 self.text.see("iomark")
1228 self.text.see("restart")
1229
1230 def restart_shell(self, event=None):
Terry Jan Reedyb98000a2012-01-31 02:09:25 -05001231 "Callback for Run/Restart Shell Cntl-F6"
1232 self.interp.restart_subprocess(with_cwd=True)
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001233
David Scherer7aced172000-08-15 01:13:23 +00001234 def showprompt(self):
1235 self.resetoutput()
1236 try:
1237 s = str(sys.ps1)
1238 except:
1239 s = ""
1240 self.console.write(s)
1241 self.text.mark_set("insert", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001242 self.set_line_and_column()
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +00001243 self.io.reset_undo()
David Scherer7aced172000-08-15 01:13:23 +00001244
1245 def resetoutput(self):
1246 source = self.text.get("iomark", "end-1c")
1247 if self.history:
1248 self.history.history_store(source)
1249 if self.text.get("end-2c") != "\n":
1250 self.text.insert("end-1c", "\n")
1251 self.text.mark_set("iomark", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001252 self.set_line_and_column()
David Scherer7aced172000-08-15 01:13:23 +00001253 sys.stdout.softspace = 0
1254
1255 def write(self, s, tags=()):
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001256 try:
1257 self.text.mark_gravity("iomark", "right")
1258 OutputWindow.write(self, s, tags, "iomark")
1259 self.text.mark_gravity("iomark", "left")
1260 except:
1261 pass
David Scherer7aced172000-08-15 01:13:23 +00001262 if self.canceled:
1263 self.canceled = 0
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001264 if not use_subprocess:
1265 raise KeyboardInterrupt
David Scherer7aced172000-08-15 01:13:23 +00001266
Andrew Svetlov5018db72012-11-01 22:39:14 +02001267 def rmenu_check_cut(self):
1268 try:
1269 if self.text.compare('sel.first', '<', 'iomark'):
1270 return 'disabled'
1271 except TclError: # no selection, so the index 'sel.first' doesn't exist
1272 return 'disabled'
1273 return super(PyShell, self).rmenu_check_cut()
1274
1275 def rmenu_check_paste(self):
1276 if self.text.compare('insert', '<', 'iomark'):
1277 return 'disabled'
1278 return super(PyShell, self).rmenu_check_paste()
1279
Serhiy Storchaka9abc8302013-01-25 15:30:35 +02001280class PseudoFile(io.TextIOBase):
David Scherer7aced172000-08-15 01:13:23 +00001281
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001282 def __init__(self, shell, tags, encoding=None):
David Scherer7aced172000-08-15 01:13:23 +00001283 self.shell = shell
1284 self.tags = tags
Chui Tey5d2af632002-05-26 13:36:41 +00001285 self.softspace = 0
Serhiy Storchaka9abc8302013-01-25 15:30:35 +02001286 self._encoding = encoding
David Scherer7aced172000-08-15 01:13:23 +00001287
Serhiy Storchaka9abc8302013-01-25 15:30:35 +02001288 @property
1289 def encoding(self):
1290 return self._encoding
David Scherer7aced172000-08-15 01:13:23 +00001291
Serhiy Storchaka9abc8302013-01-25 15:30:35 +02001292 @property
1293 def name(self):
1294 return '<%s>' % self.tags
David Scherer7aced172000-08-15 01:13:23 +00001295
1296 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001297 return True
David Scherer7aced172000-08-15 01:13:23 +00001298
Serhiy Storchaka9abc8302013-01-25 15:30:35 +02001299
1300class PseudoOutputFile(PseudoFile):
1301
1302 def writable(self):
1303 return True
Martin v. Löwise2b56242012-07-25 10:56:22 +02001304
1305 def write(self, s):
Serhiy Storchaka9abc8302013-01-25 15:30:35 +02001306 if self.closed:
1307 raise ValueError("write to closed file")
1308 if not isinstance(s, (basestring, bytearray)):
1309 raise TypeError('must be string, not ' + type(s).__name__)
1310 return self.shell.write(s, self.tags)
1311
1312
1313class PseudoInputFile(PseudoFile):
1314
1315 def __init__(self, shell, tags, encoding=None):
1316 PseudoFile.__init__(self, shell, tags, encoding)
1317 self._line_buffer = ''
1318
1319 def readable(self):
1320 return True
1321
1322 def read(self, size=-1):
1323 if self.closed:
1324 raise ValueError("read from closed file")
1325 if size is None:
1326 size = -1
1327 elif not isinstance(size, int):
1328 raise TypeError('must be int, not ' + type(size).__name__)
1329 result = self._line_buffer
1330 self._line_buffer = ''
1331 if size < 0:
1332 while True:
1333 line = self.shell.readline()
1334 if not line: break
1335 result += line
1336 else:
1337 while len(result) < size:
1338 line = self.shell.readline()
1339 if not line: break
1340 result += line
1341 self._line_buffer = result[size:]
1342 result = result[:size]
1343 return result
1344
1345 def readline(self, size=-1):
1346 if self.closed:
1347 raise ValueError("read from closed file")
1348 if size is None:
1349 size = -1
1350 elif not isinstance(size, int):
1351 raise TypeError('must be int, not ' + type(size).__name__)
1352 line = self._line_buffer or self.shell.readline()
1353 if size < 0:
1354 size = len(line)
1355 self._line_buffer = line[size:]
1356 return line[:size]
Martin v. Löwise2b56242012-07-25 10:56:22 +02001357
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001358
David Scherer7aced172000-08-15 01:13:23 +00001359usage_msg = """\
David Scherer7aced172000-08-15 01:13:23 +00001360
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001361USAGE: idle [-deins] [-t title] [file]*
1362 idle [-dns] [-t title] (-c cmd | -r file) [arg]*
1363 idle [-dns] [-t title] - [arg]*
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001364
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001365 -h print this help message and exit
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001366 -n run IDLE without a subprocess (see Help/IDLE Help for details)
David Scherer7aced172000-08-15 01:13:23 +00001367
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001368The following options will override the IDLE 'settings' configuration:
Kurt B. Kaiser96d88422001-07-17 04:59:01 +00001369
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001370 -e open an edit window
1371 -i open a shell window
1372
1373The following options imply -i and will open a shell:
1374
1375 -c cmd run the command in a shell, or
1376 -r file run script from file
1377
1378 -d enable the debugger
1379 -s run $IDLESTARTUP or $PYTHONSTARTUP before anything else
1380 -t title set title of shell window
1381
1382A default edit window will be bypassed when -c, -r, or - are used.
1383
1384[arg]* are passed to the command (-c) or script (-r) in sys.argv[1:].
1385
1386Examples:
1387
1388idle
1389 Open an edit window or shell depending on IDLE's configuration.
1390
1391idle foo.py foobar.py
1392 Edit the files, also open a shell if configured to start with shell.
1393
1394idle -est "Baz" foo.py
1395 Run $IDLESTARTUP or $PYTHONSTARTUP, edit foo.py, and open a shell
1396 window with the title "Baz".
1397
1398idle -c "import sys; print sys.argv" "foo"
1399 Open a shell window and run the command, passing "-c" in sys.argv[0]
1400 and "foo" in sys.argv[1].
1401
1402idle -d -s -r foo.py "Hello World"
1403 Open a shell window, run a startup script, enable the debugger, and
1404 run foo.py, passing "foo.py" in sys.argv[0] and "Hello World" in
1405 sys.argv[1].
1406
1407echo "import sys; print sys.argv" | idle - "foobar"
1408 Open a shell window, run the script piped in, passing '' in sys.argv[0]
1409 and "foobar" in sys.argv[1].
David Scherer7aced172000-08-15 01:13:23 +00001410"""
1411
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001412def main():
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001413 global flist, root, use_subprocess
David Scherer7aced172000-08-15 01:13:23 +00001414
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001415 use_subprocess = True
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +00001416 enable_shell = True
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001417 enable_edit = False
1418 debug = False
1419 cmd = None
1420 script = None
1421 startup = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001422 try:
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001423 opts, args = getopt.getopt(sys.argv[1:], "c:deihnr:st:")
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001424 except getopt.error, msg:
1425 sys.stderr.write("Error: %s\n" % str(msg))
1426 sys.stderr.write(usage_msg)
1427 sys.exit(2)
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001428 for o, a in opts:
1429 if o == '-c':
1430 cmd = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001431 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001432 if o == '-d':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001433 debug = True
1434 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001435 if o == '-e':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001436 enable_edit = True
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +00001437 enable_shell = False
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001438 if o == '-h':
1439 sys.stdout.write(usage_msg)
1440 sys.exit()
1441 if o == '-i':
1442 enable_shell = True
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001443 if o == '-n':
1444 use_subprocess = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001445 if o == '-r':
1446 script = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001447 if os.path.isfile(script):
1448 pass
1449 else:
1450 print "No script file: ", script
1451 sys.exit()
1452 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001453 if o == '-s':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001454 startup = True
1455 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001456 if o == '-t':
1457 PyShell.shell_title = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001458 enable_shell = True
1459 if args and args[0] == '-':
1460 cmd = sys.stdin.read()
1461 enable_shell = True
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001462 # process sys.argv and sys.path:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001463 for i in range(len(sys.path)):
1464 sys.path[i] = os.path.abspath(sys.path[i])
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001465 if args and args[0] == '-':
1466 sys.argv = [''] + args[1:]
1467 elif cmd:
1468 sys.argv = ['-c'] + args
1469 elif script:
1470 sys.argv = [script] + args
1471 elif args:
1472 enable_edit = True
1473 pathx = []
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001474 for filename in args:
1475 pathx.append(os.path.dirname(filename))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001476 for dir in pathx:
1477 dir = os.path.abspath(dir)
Florent Xiclunad630c042010-04-02 07:24:52 +00001478 if dir not in sys.path:
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001479 sys.path.insert(0, dir)
Kurt B. Kaiserff002b92002-12-21 21:39:11 +00001480 else:
1481 dir = os.getcwd()
1482 if not dir in sys.path:
1483 sys.path.insert(0, dir)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001484 # check the IDLE settings configuration (but command line overrides)
1485 edit_start = idleConf.GetOption('main', 'General',
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001486 'editor-on-startup', type='bool')
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001487 enable_edit = enable_edit or edit_start
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001488 # start editor and/or shell windows:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001489 root = Tk(className="Idle")
Ronald Oussoren19302d92006-06-11 14:33:36 +00001490
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001491 fixwordbreaks(root)
1492 root.withdraw()
1493 flist = PyShellFileList(root)
Ronald Oussoren19302d92006-06-11 14:33:36 +00001494 macosxSupport.setupApp(root, flist)
1495
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001496 if enable_edit:
1497 if not (cmd or script):
Andrew Svetlov7c010ee2012-03-21 13:35:08 +02001498 for filename in args[:]:
1499 if flist.open(filename) is None:
1500 # filename is a directory actually, disconsider it
1501 args.remove(filename)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001502 if not args:
1503 flist.new()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001504 if enable_shell:
Ronald Oussoren19302d92006-06-11 14:33:36 +00001505 shell = flist.open_shell()
1506 if not shell:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001507 return # couldn't open shell
Ronald Oussoren19302d92006-06-11 14:33:36 +00001508
1509 if macosxSupport.runningAsOSXApp() and flist.dict:
1510 # On OSX: when the user has double-clicked on a file that causes
Tim Peters4f96f1f2006-06-11 19:42:51 +00001511 # IDLE to be launched the shell window will open just in front of
1512 # the file she wants to see. Lower the interpreter window when
Ronald Oussoren19302d92006-06-11 14:33:36 +00001513 # there are open files.
1514 shell.top.lower()
1515
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001516 shell = flist.pyshell
1517 # handle remaining options:
1518 if debug:
1519 shell.open_debugger()
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001520 if startup:
1521 filename = os.environ.get("IDLESTARTUP") or \
1522 os.environ.get("PYTHONSTARTUP")
1523 if filename and os.path.isfile(filename):
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001524 shell.interp.execfile(filename)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001525 if shell and cmd or script:
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001526 shell.interp.runcommand("""if 1:
1527 import sys as _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001528 _sys.argv = %r
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001529 del _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001530 \n""" % (sys.argv,))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001531 if cmd:
1532 shell.interp.execsource(cmd)
1533 elif script:
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001534 shell.interp.prepend_syspath(script)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001535 shell.interp.execfile(script)
Ronald Oussoren19302d92006-06-11 14:33:36 +00001536
Ned Deily2a6f4b32011-01-30 00:18:47 +00001537 # Check for problematic OS X Tk versions and print a warning message
1538 # in the IDLE shell window; this is less intrusive than always opening
1539 # a separate window.
1540 tkversionwarning = macosxSupport.tkVersionWarning(root)
1541 if tkversionwarning:
1542 shell.interp.runcommand(''.join(("print('", tkversionwarning, "')")))
1543
Terry Jan Reedyeaa7e782012-05-26 20:33:32 -04001544 while flist.inversedict: # keep IDLE running while files are open.
1545 root.mainloop()
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001546 root.destroy()
1547
David Scherer7aced172000-08-15 01:13:23 +00001548if __name__ == "__main__":
Kurt B. Kaiser9e8b8282003-06-15 17:38:45 +00001549 sys.modules['PyShell'] = sys.modules['__main__']
David Scherer7aced172000-08-15 01:13:23 +00001550 main()