blob: d6f3ce3f64b81c7e0d5ce2f7b9ef9cecaf2f26bd [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
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000125 rmenu_specs = [("Set Breakpoint", "<<set-breakpoint-here>>"),
126 ("Clear Breakpoint", "<<clear-breakpoint-here>>")]
David Scherer7aced172000-08-15 01:13:23 +0000127
Chui Teya2adb0f2002-11-04 22:14:54 +0000128 def set_breakpoint(self, lineno):
129 text = self.text
130 filename = self.io.filename
131 text.tag_add("BREAK", "%d.0" % lineno, "%d.0" % (lineno+1))
132 try:
133 i = self.breakpoints.index(lineno)
134 except ValueError: # only add if missing, i.e. do once
135 self.breakpoints.append(lineno)
136 try: # update the subprocess debugger
137 debug = self.flist.pyshell.interp.debugger
138 debug.set_breakpoint_here(filename, lineno)
139 except: # but debugger may not be active right now....
140 pass
141
David Scherer7aced172000-08-15 01:13:23 +0000142 def set_breakpoint_here(self, event=None):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000143 text = self.text
144 filename = self.io.filename
145 if not filename:
146 text.bell()
David Scherer7aced172000-08-15 01:13:23 +0000147 return
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000148 lineno = int(float(text.index("insert")))
Chui Teya2adb0f2002-11-04 22:14:54 +0000149 self.set_breakpoint(lineno)
David Scherer7aced172000-08-15 01:13:23 +0000150
Kurt B. Kaiser669f4c32002-06-20 04:01:47 +0000151 def clear_breakpoint_here(self, event=None):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000152 text = self.text
153 filename = self.io.filename
154 if not filename:
155 text.bell()
Kurt B. Kaiser669f4c32002-06-20 04:01:47 +0000156 return
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000157 lineno = int(float(text.index("insert")))
158 try:
159 self.breakpoints.remove(lineno)
160 except:
161 pass
162 text.tag_remove("BREAK", "insert linestart",\
163 "insert lineend +1char")
164 try:
165 debug = self.flist.pyshell.interp.debugger
166 debug.clear_breakpoint_here(filename, lineno)
167 except:
168 pass
169
170 def clear_file_breaks(self):
171 if self.breakpoints:
172 text = self.text
173 filename = self.io.filename
174 if not filename:
175 text.bell()
176 return
177 self.breakpoints = []
178 text.tag_remove("BREAK", "1.0", END)
179 try:
180 debug = self.flist.pyshell.interp.debugger
181 debug.clear_file_breaks(filename)
182 except:
183 pass
184
Chui Teya2adb0f2002-11-04 22:14:54 +0000185 def store_file_breaks(self):
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000186 "Save breakpoints when file is saved"
187 # XXX 13 Dec 2002 KBK Currently the file must be saved before it can
188 # be run. The breaks are saved at that time. If we introduce
189 # a temporary file save feature the save breaks functionality
190 # needs to be re-verified, since the breaks at the time the
191 # temp file is created may differ from the breaks at the last
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000192 # permanent save of the file. Currently, a break introduced
193 # after a save will be effective, but not persistent.
194 # This is necessary to keep the saved breaks synched with the
195 # saved file.
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000196 #
197 # Breakpoints are set as tagged ranges in the text. Certain
198 # kinds of edits cause these ranges to be deleted: Inserting
199 # or deleting a line just before a breakpoint, and certain
200 # deletions prior to a breakpoint. These issues need to be
201 # investigated and understood. It's not clear if they are
202 # Tk issues or IDLE issues, or whether they can actually
203 # be fixed. Since a modified file has to be saved before it is
204 # run, and since self.breakpoints (from which the subprocess
205 # debugger is loaded) is updated during the save, the visible
206 # breaks stay synched with the subprocess even if one of these
207 # unexpected breakpoint deletions occurs.
208 breaks = self.breakpoints
209 filename = self.io.filename
Chui Teya2adb0f2002-11-04 22:14:54 +0000210 try:
Ned Deily40ad0412011-12-14 14:57:43 -0800211 with open(self.breakpointPath,"r") as old_file:
212 lines = old_file.readlines()
Chui Teya2adb0f2002-11-04 22:14:54 +0000213 except IOError:
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000214 lines = []
Ned Deily40ad0412011-12-14 14:57:43 -0800215 try:
216 with open(self.breakpointPath,"w") as new_file:
217 for line in lines:
218 if not line.startswith(filename + '='):
219 new_file.write(line)
220 self.update_breakpoints()
221 breaks = self.breakpoints
222 if breaks:
223 new_file.write(filename + '=' + str(breaks) + '\n')
224 except IOError as err:
225 if not getattr(self.root, "breakpoint_error_displayed", False):
226 self.root.breakpoint_error_displayed = True
227 tkMessageBox.showerror(title='IDLE Error',
228 message='Unable to update breakpoint list:\n%s'
229 % str(err),
230 parent=self.text)
Chui Teya2adb0f2002-11-04 22:14:54 +0000231
232 def restore_file_breaks(self):
233 self.text.update() # this enables setting "BREAK" tags to be visible
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000234 filename = self.io.filename
235 if filename is None:
236 return
Chui Tey69371d62002-11-04 23:39:45 +0000237 if os.path.isfile(self.breakpointPath):
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000238 lines = open(self.breakpointPath,"r").readlines()
Chui Tey69371d62002-11-04 23:39:45 +0000239 for line in lines:
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000240 if line.startswith(filename + '='):
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000241 breakpoint_linenumbers = eval(line[len(filename)+1:])
Chui Tey69371d62002-11-04 23:39:45 +0000242 for breakpoint_linenumber in breakpoint_linenumbers:
243 self.set_breakpoint(breakpoint_linenumber)
Chui Teya2adb0f2002-11-04 22:14:54 +0000244
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000245 def update_breakpoints(self):
246 "Retrieves all the breakpoints in the current window"
Chui Teya2adb0f2002-11-04 22:14:54 +0000247 text = self.text
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000248 ranges = text.tag_ranges("BREAK")
249 linenumber_list = self.ranges_to_linenumbers(ranges)
250 self.breakpoints = linenumber_list
251
252 def ranges_to_linenumbers(self, ranges):
253 lines = []
254 for index in range(0, len(ranges), 2):
Andrew Svetlov8a15c372012-07-31 19:51:27 +0300255 lineno = int(float(ranges[index].string))
256 end = int(float(ranges[index+1].string))
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000257 while lineno < end:
258 lines.append(lineno)
259 lineno += 1
260 return lines
261
Kurt B. Kaiser11220fa2002-12-24 00:57:22 +0000262# XXX 13 Dec 2002 KBK Not used currently
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000263# def saved_change_hook(self):
264# "Extend base method - clear breaks if module is modified"
265# if not self.get_saved():
266# self.clear_file_breaks()
267# EditorWindow.saved_change_hook(self)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000268
269 def _close(self):
270 "Extend base method - clear breaks when module is closed"
271 self.clear_file_breaks()
272 EditorWindow._close(self)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000273
David Scherer7aced172000-08-15 01:13:23 +0000274
275class PyShellFileList(FileList):
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000276 "Extend base class: IDLE supports a shell and breakpoints"
David Scherer7aced172000-08-15 01:13:23 +0000277
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000278 # override FileList's class variable, instances return PyShellEditorWindow
279 # instead of EditorWindow when new edit windows are created.
David Scherer7aced172000-08-15 01:13:23 +0000280 EditorWindow = PyShellEditorWindow
281
282 pyshell = None
283
284 def open_shell(self, event=None):
285 if self.pyshell:
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000286 self.pyshell.top.wakeup()
David Scherer7aced172000-08-15 01:13:23 +0000287 else:
288 self.pyshell = PyShell(self)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000289 if self.pyshell:
290 if not self.pyshell.begin():
291 return None
David Scherer7aced172000-08-15 01:13:23 +0000292 return self.pyshell
293
294
295class ModifiedColorDelegator(ColorDelegator):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000296 "Extend base class: colorizer for the shell window itself"
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000297
Steven M. Gavab77d3432002-03-02 07:16:21 +0000298 def __init__(self):
299 ColorDelegator.__init__(self)
300 self.LoadTagDefs()
David Scherer7aced172000-08-15 01:13:23 +0000301
302 def recolorize_main(self):
303 self.tag_remove("TODO", "1.0", "iomark")
304 self.tag_add("SYNC", "1.0", "iomark")
305 ColorDelegator.recolorize_main(self)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000306
Steven M. Gavab77d3432002-03-02 07:16:21 +0000307 def LoadTagDefs(self):
308 ColorDelegator.LoadTagDefs(self)
309 theme = idleConf.GetOption('main','Theme','name')
310 self.tagdefs.update({
311 "stdin": {'background':None,'foreground':None},
312 "stdout": idleConf.GetHighlight(theme, "stdout"),
313 "stderr": idleConf.GetHighlight(theme, "stderr"),
314 "console": idleConf.GetHighlight(theme, "console"),
Steven M. Gavab77d3432002-03-02 07:16:21 +0000315 })
David Scherer7aced172000-08-15 01:13:23 +0000316
Ned Deily5e247b72012-05-31 09:17:29 -0700317 def removecolors(self):
318 # Don't remove shell color tags before "iomark"
319 for tag in self.tagdefs:
320 self.tag_remove(tag, "iomark", "end")
321
David Scherer7aced172000-08-15 01:13:23 +0000322class ModifiedUndoDelegator(UndoDelegator):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000323 "Extend base class: forbid insert/delete before the I/O mark"
David Scherer7aced172000-08-15 01:13:23 +0000324
325 def insert(self, index, chars, tags=None):
326 try:
327 if self.delegate.compare(index, "<", "iomark"):
328 self.delegate.bell()
329 return
330 except TclError:
331 pass
332 UndoDelegator.insert(self, index, chars, tags)
333
334 def delete(self, index1, index2=None):
335 try:
336 if self.delegate.compare(index1, "<", "iomark"):
337 self.delegate.bell()
338 return
339 except TclError:
340 pass
341 UndoDelegator.delete(self, index1, index2)
342
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000343
344class MyRPCClient(rpc.RPCClient):
345
346 def handle_EOF(self):
347 "Override the base class - just re-raise EOFError"
348 raise EOFError
349
Kurt B. Kaiser8d1f11b2003-05-26 22:20:34 +0000350
David Scherer7aced172000-08-15 01:13:23 +0000351class ModifiedInterpreter(InteractiveInterpreter):
352
353 def __init__(self, tkconsole):
354 self.tkconsole = tkconsole
355 locals = sys.modules['__main__'].__dict__
356 InteractiveInterpreter.__init__(self, locals=locals)
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000357 self.save_warnings_filters = None
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000358 self.restarting = False
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +0000359 self.subprocess_arglist = None
360 self.port = PORT
Ned Deily86d669b2011-10-30 19:58:04 -0700361 self.original_compiler_flags = self.compile.compiler.flags
David Scherer7aced172000-08-15 01:13:23 +0000362
Chui Tey5d2af632002-05-26 13:36:41 +0000363 rpcclt = None
364 rpcpid = None
365
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000366 def spawn_subprocess(self):
Florent Xiclunac8a730b2010-03-25 20:32:07 +0000367 if self.subprocess_arglist is None:
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +0000368 self.subprocess_arglist = self.build_subprocess_arglist()
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000369 args = self.subprocess_arglist
Kurt B. Kaiserb7855182003-08-14 14:54:28 +0000370 self.rpcpid = os.spawnv(os.P_NOWAIT, sys.executable, args)
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000371
Tony Lowndsf53dec22002-12-20 04:24:43 +0000372 def build_subprocess_arglist(self):
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +0000373 assert (self.port!=0), (
374 "Socket should have been assigned a port number.")
Tony Lownds2398d572003-05-13 15:28:21 +0000375 w = ['-W' + s for s in sys.warnoptions]
Georg Brandld0761532006-10-12 07:57:21 +0000376 if 1/2 > 0: # account for new division
377 w.append('-Qnew')
Tony Lownds2398d572003-05-13 15:28:21 +0000378 # Maybe IDLE is installed and is being accessed via sys.path,
379 # or maybe it's not installed and the idle.py script is being
380 # run from the IDLE source directory.
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000381 del_exitf = idleConf.GetOption('main', 'General', 'delete-exitfunc',
382 default=False, type='bool')
Tony Lownds2398d572003-05-13 15:28:21 +0000383 if __name__ == 'idlelib.PyShell':
Walter Dörwald70a6b492004-02-12 17:35:32 +0000384 command = "__import__('idlelib.run').run.main(%r)" % (del_exitf,)
Tony Lowndsf2324b92002-09-29 00:34:10 +0000385 else:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000386 command = "__import__('run').main(%r)" % (del_exitf,)
Kurt B. Kaiserb7855182003-08-14 14:54:28 +0000387 if sys.platform[:3] == 'win' and ' ' in sys.executable:
388 # handle embedded space in path by quoting the argument
389 decorated_exec = '"%s"' % sys.executable
390 else:
391 decorated_exec = sys.executable
392 return [decorated_exec] + w + ["-c", command, str(self.port)]
Tony Lowndsf2324b92002-09-29 00:34:10 +0000393
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000394 def start_subprocess(self):
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +0000395 addr = (HOST, self.port)
396 # GUI makes several attempts to acquire socket, listens for connection
Kurt B. Kaiser5db48432003-05-15 03:40:51 +0000397 for i in range(3):
Chui Tey5d2af632002-05-26 13:36:41 +0000398 time.sleep(i)
399 try:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000400 self.rpcclt = MyRPCClient(addr)
Chui Tey5d2af632002-05-26 13:36:41 +0000401 break
402 except socket.error, err:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000403 pass
Chui Tey5d2af632002-05-26 13:36:41 +0000404 else:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000405 self.display_port_binding_error()
406 return None
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +0000407 # if PORT was 0, system will assign an 'ephemeral' port. Find it out:
408 self.port = self.rpcclt.listening_sock.getsockname()[1]
409 # if PORT was not 0, probably working with a remote execution server
410 if PORT != 0:
411 # To allow reconnection within the 2MSL wait (cf. Stevens TCP
412 # V1, 18.6), set SO_REUSEADDR. Note that this can be problematic
413 # on Windows since the implementation allows two active sockets on
414 # the same address!
415 self.rpcclt.listening_sock.setsockopt(socket.SOL_SOCKET,
416 socket.SO_REUSEADDR, 1)
417 self.spawn_subprocess()
418 #time.sleep(20) # test to simulate GUI not accepting connection
Kurt B. Kaiserb4179362002-07-26 00:06:42 +0000419 # Accept the connection from the Python execution server
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000420 self.rpcclt.listening_sock.settimeout(10)
421 try:
422 self.rpcclt.accept()
423 except socket.timeout, err:
424 self.display_no_subprocess_error()
425 return None
Martin v. Löwise2b56242012-07-25 10:56:22 +0200426 # Can't regiter self.tkconsole.stdin, since run.py wants to
427 # call non-TextIO methods on it (such as getvar)
428 # XXX should be renamed to "console"
Kurt B. Kaiser969de452002-06-12 03:28:57 +0000429 self.rpcclt.register("stdin", self.tkconsole)
430 self.rpcclt.register("stdout", self.tkconsole.stdout)
431 self.rpcclt.register("stderr", self.tkconsole.stderr)
Chui Tey5d2af632002-05-26 13:36:41 +0000432 self.rpcclt.register("flist", self.tkconsole.flist)
Kurt B. Kaiser8cd0def2003-01-31 05:06:43 +0000433 self.rpcclt.register("linecache", linecache)
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000434 self.rpcclt.register("interp", self)
Terry Jan Reedyb98000a2012-01-31 02:09:25 -0500435 self.transfer_path(with_cwd=True)
Chui Tey5d2af632002-05-26 13:36:41 +0000436 self.poll_subprocess()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000437 return self.rpcclt
Chui Tey5d2af632002-05-26 13:36:41 +0000438
Terry Jan Reedyb98000a2012-01-31 02:09:25 -0500439 def restart_subprocess(self, with_cwd=False):
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000440 if self.restarting:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000441 return self.rpcclt
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000442 self.restarting = True
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000443 # close only the subprocess debugger
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000444 debug = self.getdebugger()
445 if debug:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000446 try:
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000447 # Only close subprocess debugger, don't unregister gui_adap!
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000448 RemoteDebugger.close_subprocess_debugger(self.rpcclt)
449 except:
450 pass
451 # Kill subprocess, spawn a new one, accept connection.
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000452 self.rpcclt.close()
453 self.unix_terminate()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000454 console = self.tkconsole
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000455 was_executing = console.executing
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000456 console.executing = False
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000457 self.spawn_subprocess()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000458 try:
459 self.rpcclt.accept()
460 except socket.timeout, err:
461 self.display_no_subprocess_error()
462 return None
Terry Jan Reedyb98000a2012-01-31 02:09:25 -0500463 self.transfer_path(with_cwd=with_cwd)
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000464 # annotate restart in shell window and mark it
Kurt B. Kaiser4cc5ef52003-01-22 00:23:23 +0000465 console.text.delete("iomark", "end-1c")
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000466 if was_executing:
467 console.write('\n')
468 console.showprompt()
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000469 halfbar = ((int(console.width) - 16) // 2) * '='
470 console.write(halfbar + ' RESTART ' + halfbar)
471 console.text.mark_set("restart", "end-1c")
472 console.text.mark_gravity("restart", "left")
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000473 console.showprompt()
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000474 # restart subprocess debugger
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000475 if debug:
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000476 # Restarted debugger connects to current instance of debug GUI
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000477 gui = RemoteDebugger.restart_subprocess_debugger(self.rpcclt)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000478 # reload remote debugger breakpoints for all PyShellEditWindows
479 debug.load_breakpoints()
Ned Deily86d669b2011-10-30 19:58:04 -0700480 self.compile.compiler.flags = self.original_compiler_flags
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000481 self.restarting = False
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000482 return self.rpcclt
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000483
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000484 def __request_interrupt(self):
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000485 self.rpcclt.remotecall("exec", "interrupt_the_server", (), {})
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000486
487 def interrupt_subprocess(self):
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000488 threading.Thread(target=self.__request_interrupt).start()
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000489
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000490 def kill_subprocess(self):
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000491 try:
492 self.rpcclt.close()
493 except AttributeError: # no socket
494 pass
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000495 self.unix_terminate()
496 self.tkconsole.executing = False
497 self.rpcclt = None
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000498
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000499 def unix_terminate(self):
500 "UNIX: make sure subprocess is terminated and collect status"
501 if hasattr(os, 'kill'):
502 try:
503 os.kill(self.rpcpid, SIGTERM)
504 except OSError:
505 # process already terminated:
506 return
507 else:
508 try:
509 os.waitpid(self.rpcpid, 0)
510 except OSError:
511 return
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000512
Terry Jan Reedyb98000a2012-01-31 02:09:25 -0500513 def transfer_path(self, with_cwd=False):
514 if with_cwd: # Issue 13506
515 path = [''] # include Current Working Directory
516 path.extend(sys.path)
517 else:
518 path = sys.path
Terry Jan Reedy1d4ae482012-01-31 02:55:32 -0500519
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000520 self.runcommand("""if 1:
521 import sys as _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +0000522 _sys.path = %r
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000523 del _sys
Terry Jan Reedyb98000a2012-01-31 02:09:25 -0500524 \n""" % (path,))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000525
Chui Tey5d2af632002-05-26 13:36:41 +0000526 active_seq = None
527
528 def poll_subprocess(self):
529 clt = self.rpcclt
530 if clt is None:
531 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000532 try:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000533 response = clt.pollresponse(self.active_seq, wait=0.05)
534 except (EOFError, IOError, KeyboardInterrupt):
535 # lost connection or subprocess terminated itself, restart
536 # [the KBI is from rpc.SocketIO.handle_EOF()]
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000537 if self.tkconsole.closing:
538 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000539 response = None
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000540 self.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000541 if response:
542 self.tkconsole.resetoutput()
543 self.active_seq = None
544 how, what = response
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000545 console = self.tkconsole.console
Chui Tey5d2af632002-05-26 13:36:41 +0000546 if how == "OK":
547 if what is not None:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000548 print >>console, repr(what)
Chui Tey5d2af632002-05-26 13:36:41 +0000549 elif how == "EXCEPTION":
Chui Tey5d2af632002-05-26 13:36:41 +0000550 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
551 self.remote_stack_viewer()
552 elif how == "ERROR":
Kurt B. Kaiser0930c432002-12-06 21:45:24 +0000553 errmsg = "PyShell.ModifiedInterpreter: Subprocess ERROR:\n"
554 print >>sys.__stderr__, errmsg, what
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000555 print >>console, errmsg, what
556 # we received a response to the currently active seq number:
Kurt B. Kaiserd112bc72006-08-16 05:01:42 +0000557 try:
558 self.tkconsole.endexecuting()
559 except AttributeError: # shell may have closed
560 pass
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000561 # Reschedule myself
562 if not self.tkconsole.closing:
563 self.tkconsole.text.after(self.tkconsole.pollinterval,
564 self.poll_subprocess)
Chui Tey5d2af632002-05-26 13:36:41 +0000565
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000566 debugger = None
567
568 def setdebugger(self, debugger):
569 self.debugger = debugger
570
571 def getdebugger(self):
572 return self.debugger
573
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000574 def open_remote_stack_viewer(self):
575 """Initiate the remote stack viewer from a separate thread.
576
577 This method is called from the subprocess, and by returning from this
578 method we allow the subprocess to unblock. After a bit the shell
579 requests the subprocess to open the remote stack viewer which returns a
Ezio Melottic569cfe2010-07-23 16:55:21 +0000580 static object looking at the last exception. It is queried through
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000581 the RPC mechanism.
582
583 """
584 self.tkconsole.text.after(300, self.remote_stack_viewer)
585 return
586
Chui Tey5d2af632002-05-26 13:36:41 +0000587 def remote_stack_viewer(self):
Florent Xiclunad630c042010-04-02 07:24:52 +0000588 from idlelib import RemoteObjectBrowser
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000589 oid = self.rpcclt.remotequeue("exec", "stackviewer", ("flist",), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000590 if oid is None:
591 self.tkconsole.root.bell()
592 return
593 item = RemoteObjectBrowser.StubObjectTreeItem(self.rpcclt, oid)
Florent Xiclunad630c042010-04-02 07:24:52 +0000594 from idlelib.TreeWidget import ScrolledCanvas, TreeNode
Chui Tey5d2af632002-05-26 13:36:41 +0000595 top = Toplevel(self.tkconsole.root)
Kurt B. Kaiser73360a32004-03-08 18:15:31 +0000596 theme = idleConf.GetOption('main','Theme','name')
597 background = idleConf.GetHighlight(theme, 'normal')['background']
598 sc = ScrolledCanvas(top, bg=background, highlightthickness=0)
Chui Tey5d2af632002-05-26 13:36:41 +0000599 sc.frame.pack(expand=1, fill="both")
600 node = TreeNode(sc.canvas, None, item)
601 node.expand()
602 # XXX Should GC the remote tree when closing the window
603
David Scherer7aced172000-08-15 01:13:23 +0000604 gid = 0
605
606 def execsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000607 "Like runsource() but assumes complete exec source"
David Scherer7aced172000-08-15 01:13:23 +0000608 filename = self.stuffsource(source)
609 self.execfile(filename, source)
610
611 def execfile(self, filename, source=None):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000612 "Execute an existing file"
David Scherer7aced172000-08-15 01:13:23 +0000613 if source is None:
614 source = open(filename, "r").read()
615 try:
616 code = compile(source, filename, "exec")
617 except (OverflowError, SyntaxError):
618 self.tkconsole.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000619 tkerr = self.tkconsole.stderr
620 print>>tkerr, '*** Error in script or command!\n'
621 print>>tkerr, 'Traceback (most recent call last):'
David Scherer7aced172000-08-15 01:13:23 +0000622 InteractiveInterpreter.showsyntaxerror(self, filename)
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000623 self.tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000624 else:
625 self.runcode(code)
626
627 def runsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000628 "Extend base class method: Stuff the source in the line cache first"
David Scherer7aced172000-08-15 01:13:23 +0000629 filename = self.stuffsource(source)
630 self.more = 0
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000631 self.save_warnings_filters = warnings.filters[:]
632 warnings.filterwarnings(action="error", category=SyntaxWarning)
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000633 if isinstance(source, types.UnicodeType):
Florent Xiclunad630c042010-04-02 07:24:52 +0000634 from idlelib import IOBinding
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000635 try:
636 source = source.encode(IOBinding.encoding)
637 except UnicodeError:
638 self.tkconsole.resetoutput()
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +0000639 self.write("Unsupported characters in input\n")
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000640 return
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000641 try:
Kurt B. Kaiser935ea9a2005-05-10 03:44:24 +0000642 # InteractiveInterpreter.runsource() calls its runcode() method,
643 # which is overridden (see below)
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000644 return InteractiveInterpreter.runsource(self, source, filename)
645 finally:
646 if self.save_warnings_filters is not None:
647 warnings.filters[:] = self.save_warnings_filters
648 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000649
650 def stuffsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000651 "Stuff source in the filename cache"
David Scherer7aced172000-08-15 01:13:23 +0000652 filename = "<pyshell#%d>" % self.gid
653 self.gid = self.gid + 1
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000654 lines = source.split("\n")
David Scherer7aced172000-08-15 01:13:23 +0000655 linecache.cache[filename] = len(source)+1, 0, lines, filename
656 return filename
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000657
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000658 def prepend_syspath(self, filename):
659 "Prepend sys.path with file's directory if not already included"
660 self.runcommand("""if 1:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000661 _filename = %r
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000662 import sys as _sys
663 from os.path import dirname as _dirname
664 _dir = _dirname(_filename)
665 if not _dir in _sys.path:
666 _sys.path.insert(0, _dir)
667 del _filename, _sys, _dirname, _dir
Walter Dörwald70a6b492004-02-12 17:35:32 +0000668 \n""" % (filename,))
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000669
David Scherer7aced172000-08-15 01:13:23 +0000670 def showsyntaxerror(self, filename=None):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000671 """Extend base class method: Add Colorizing
672
673 Color the offending position instead of printing it and pointing at it
674 with a caret.
675
676 """
David Scherer7aced172000-08-15 01:13:23 +0000677 text = self.tkconsole.text
678 stuff = self.unpackerror()
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000679 if stuff:
680 msg, lineno, offset, line = stuff
681 if lineno == 1:
682 pos = "iomark + %d chars" % (offset-1)
683 else:
684 pos = "iomark linestart + %d lines + %d chars" % \
685 (lineno-1, offset-1)
686 text.tag_add("ERROR", pos)
687 text.see(pos)
688 char = text.get(pos)
689 if char and char in IDENTCHARS:
690 text.tag_add("ERROR", pos + " wordstart", pos)
691 self.tkconsole.resetoutput()
692 self.write("SyntaxError: %s\n" % str(msg))
693 else:
David Scherer7aced172000-08-15 01:13:23 +0000694 self.tkconsole.resetoutput()
695 InteractiveInterpreter.showsyntaxerror(self, filename)
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000696 self.tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000697
698 def unpackerror(self):
699 type, value, tb = sys.exc_info()
700 ok = type is SyntaxError
701 if ok:
702 try:
703 msg, (dummy_filename, lineno, offset, line) = value
Kurt B. Kaiserbea57c62003-07-09 04:27:24 +0000704 if not offset:
705 offset = 0
David Scherer7aced172000-08-15 01:13:23 +0000706 except:
707 ok = 0
708 if ok:
709 return msg, lineno, offset, line
710 else:
711 return None
712
713 def showtraceback(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000714 "Extend base class method to reset output properly"
David Scherer7aced172000-08-15 01:13:23 +0000715 self.tkconsole.resetoutput()
716 self.checklinecache()
717 InteractiveInterpreter.showtraceback(self)
Chui Tey5d2af632002-05-26 13:36:41 +0000718 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
719 self.tkconsole.open_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +0000720
721 def checklinecache(self):
722 c = linecache.cache
723 for key in c.keys():
724 if key[:1] + key[-1:] != "<>":
725 del c[key]
726
Chui Tey5d2af632002-05-26 13:36:41 +0000727 def runcommand(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000728 "Run the code without invoking the debugger"
Chui Tey5d2af632002-05-26 13:36:41 +0000729 # The code better not raise an exception!
730 if self.tkconsole.executing:
Neal Norwitzf4c4f112002-11-30 18:49:10 +0000731 self.display_executing_dialog()
Chui Tey5d2af632002-05-26 13:36:41 +0000732 return 0
733 if self.rpcclt:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000734 self.rpcclt.remotequeue("exec", "runcode", (code,), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000735 else:
736 exec code in self.locals
737 return 1
738
David Scherer7aced172000-08-15 01:13:23 +0000739 def runcode(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000740 "Override base class method"
Chui Tey5d2af632002-05-26 13:36:41 +0000741 if self.tkconsole.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000742 self.interp.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000743 self.checklinecache()
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000744 if self.save_warnings_filters is not None:
745 warnings.filters[:] = self.save_warnings_filters
746 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000747 debugger = self.debugger
748 try:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000749 self.tkconsole.beginexecuting()
Kurt B. Kaiserdddeb0e2007-02-06 03:21:40 +0000750 if not debugger and self.rpcclt is not None:
751 self.active_seq = self.rpcclt.asyncqueue("exec", "runcode",
752 (code,), {})
753 elif debugger:
754 debugger.run(code, self.locals)
755 else:
756 exec code in self.locals
757 except SystemExit:
758 if not self.tkconsole.closing:
759 if tkMessageBox.askyesno(
760 "Exit?",
761 "Do you want to exit altogether?",
762 default="yes",
763 master=self.tkconsole.text):
Kurt B. Kaiserf137e1d2006-08-16 07:04:17 +0000764 raise
Kurt B. Kaiserdddeb0e2007-02-06 03:21:40 +0000765 else:
766 self.showtraceback()
767 else:
768 raise
769 except:
770 if use_subprocess:
771 print >>self.tkconsole.stderr, \
772 "IDLE internal error in runcode()"
David Scherer7aced172000-08-15 01:13:23 +0000773 self.showtraceback()
Kurt B. Kaiserdddeb0e2007-02-06 03:21:40 +0000774 self.tkconsole.endexecuting()
775 else:
776 if self.tkconsole.canceled:
777 self.tkconsole.canceled = False
778 print >>self.tkconsole.stderr, "KeyboardInterrupt"
779 else:
780 self.showtraceback()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000781 finally:
782 if not use_subprocess:
Kurt B. Kaiserd112bc72006-08-16 05:01:42 +0000783 try:
784 self.tkconsole.endexecuting()
785 except AttributeError: # shell may have closed
786 pass
David Scherer7aced172000-08-15 01:13:23 +0000787
788 def write(self, s):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000789 "Override base class method"
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000790 self.tkconsole.stderr.write(s)
David Scherer7aced172000-08-15 01:13:23 +0000791
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000792 def display_port_binding_error(self):
793 tkMessageBox.showerror(
794 "Port Binding Error",
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +0000795 "IDLE can't bind to a TCP/IP port, which is necessary to "
796 "communicate with its Python execution server. This might be "
797 "because no networking is installed on this computer. "
798 "Run IDLE with the -n command line switch to start without a "
799 "subprocess and refer to Help/IDLE Help 'Running without a "
800 "subprocess' for further details.",
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000801 master=self.tkconsole.text)
802
803 def display_no_subprocess_error(self):
804 tkMessageBox.showerror(
805 "Subprocess Startup Error",
806 "IDLE's subprocess didn't make connection. Either IDLE can't "
807 "start a subprocess or personal firewall software is blocking "
808 "the connection.",
809 master=self.tkconsole.text)
810
811 def display_executing_dialog(self):
812 tkMessageBox.showerror(
813 "Already executing",
814 "The Python Shell window is already executing a command; "
815 "please wait until it is finished.",
816 master=self.tkconsole.text)
817
818
David Scherer7aced172000-08-15 01:13:23 +0000819class PyShell(OutputWindow):
820
821 shell_title = "Python Shell"
822
823 # Override classes
824 ColorDelegator = ModifiedColorDelegator
825 UndoDelegator = ModifiedUndoDelegator
826
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000827 # Override menus
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000828 menu_specs = [
829 ("file", "_File"),
830 ("edit", "_Edit"),
Kurt B. Kaiser4cc5ef52003-01-22 00:23:23 +0000831 ("debug", "_Debug"),
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000832 ("options", "_Options"),
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000833 ("windows", "_Windows"),
834 ("help", "_Help"),
835 ]
David Scherer7aced172000-08-15 01:13:23 +0000836
Ronald Oussoren19302d92006-06-11 14:33:36 +0000837 if macosxSupport.runningAsOSXApp():
838 del menu_specs[-3]
839 menu_specs[-2] = ("windows", "_Window")
840
841
David Scherer7aced172000-08-15 01:13:23 +0000842 # New classes
Florent Xiclunad630c042010-04-02 07:24:52 +0000843 from idlelib.IdleHistory import History
David Scherer7aced172000-08-15 01:13:23 +0000844
845 def __init__(self, flist=None):
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000846 if use_subprocess:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000847 ms = self.menu_specs
848 if ms[2][0] != "shell":
Kurt B. Kaiser7ae35482006-08-16 21:45:59 +0000849 ms.insert(2, ("shell", "She_ll"))
David Scherer7aced172000-08-15 01:13:23 +0000850 self.interp = ModifiedInterpreter(self)
851 if flist is None:
852 root = Tk()
853 fixwordbreaks(root)
854 root.withdraw()
855 flist = PyShellFileList(root)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000856 #
David Scherer7aced172000-08-15 01:13:23 +0000857 OutputWindow.__init__(self, flist, None, None)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000858 #
Kurt B. Kaiser6af44982005-01-19 00:22:59 +0000859## self.config(usetabs=1, indentwidth=8, context_use_ps1=1)
860 self.usetabs = True
861 # indentwidth must be 8 when using tabs. See note in EditorWindow:
862 self.indentwidth = 8
863 self.context_use_ps1 = True
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000864 #
David Scherer7aced172000-08-15 01:13:23 +0000865 text = self.text
866 text.configure(wrap="char")
867 text.bind("<<newline-and-indent>>", self.enter_callback)
868 text.bind("<<plain-newline-and-indent>>", self.linefeed_callback)
869 text.bind("<<interrupt-execution>>", self.cancel_callback)
David Scherer7aced172000-08-15 01:13:23 +0000870 text.bind("<<end-of-file>>", self.eof_callback)
871 text.bind("<<open-stack-viewer>>", self.open_stack_viewer)
Kurt B. Kaiser57bfe5d2003-05-10 00:09:52 +0000872 text.bind("<<toggle-debugger>>", self.toggle_debugger)
David Scherer7aced172000-08-15 01:13:23 +0000873 text.bind("<<toggle-jit-stack-viewer>>", self.toggle_jit_stack_viewer)
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000874 if use_subprocess:
875 text.bind("<<view-restart>>", self.view_restart_mark)
876 text.bind("<<restart-shell>>", self.restart_shell)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000877 #
David Scherer7aced172000-08-15 01:13:23 +0000878 self.save_stdout = sys.stdout
879 self.save_stderr = sys.stderr
880 self.save_stdin = sys.stdin
Florent Xiclunad630c042010-04-02 07:24:52 +0000881 from idlelib import IOBinding
Martin v. Löwise2b56242012-07-25 10:56:22 +0200882 self.stdin = PseudoInputFile(self)
Martin v. Löwisbcc651a2003-06-22 07:52:56 +0000883 self.stdout = PseudoFile(self, "stdout", IOBinding.encoding)
884 self.stderr = PseudoFile(self, "stderr", IOBinding.encoding)
885 self.console = PseudoFile(self, "console", IOBinding.encoding)
Chui Tey5d2af632002-05-26 13:36:41 +0000886 if not use_subprocess:
887 sys.stdout = self.stdout
888 sys.stderr = self.stderr
Martin v. Löwise2b56242012-07-25 10:56:22 +0200889 sys.stdin = self.stdin
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000890 #
David Scherer7aced172000-08-15 01:13:23 +0000891 self.history = self.History(self.text)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000892 #
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000893 self.pollinterval = 50 # millisec
Chui Tey5d2af632002-05-26 13:36:41 +0000894
Kurt B. Kaiser4d5bc602004-06-06 01:29:22 +0000895 def get_standard_extension_names(self):
896 return idleConf.GetExtensions(shell_only=True)
897
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000898 reading = False
899 executing = False
900 canceled = False
901 endoffile = False
902 closing = False
David Scherer7aced172000-08-15 01:13:23 +0000903
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +0000904 def set_warning_stream(self, stream):
Skip Montanarod9161422004-07-06 21:53:27 +0000905 global warning_stream
906 warning_stream = stream
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +0000907
908 def get_warning_stream(self):
909 return warning_stream
910
David Scherer7aced172000-08-15 01:13:23 +0000911 def toggle_debugger(self, event=None):
912 if self.executing:
913 tkMessageBox.showerror("Don't debug now",
914 "You can only toggle the debugger when idle",
915 master=self.text)
916 self.set_debugger_indicator()
917 return "break"
918 else:
919 db = self.interp.getdebugger()
920 if db:
921 self.close_debugger()
922 else:
923 self.open_debugger()
924
925 def set_debugger_indicator(self):
926 db = self.interp.getdebugger()
927 self.setvar("<<toggle-debugger>>", not not db)
928
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000929 def toggle_jit_stack_viewer(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +0000930 pass # All we need is the variable
931
932 def close_debugger(self):
933 db = self.interp.getdebugger()
934 if db:
935 self.interp.setdebugger(None)
936 db.close()
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000937 if self.interp.rpcclt:
938 RemoteDebugger.close_remote_debugger(self.interp.rpcclt)
David Scherer7aced172000-08-15 01:13:23 +0000939 self.resetoutput()
940 self.console.write("[DEBUG OFF]\n")
941 sys.ps1 = ">>> "
942 self.showprompt()
943 self.set_debugger_indicator()
944
945 def open_debugger(self):
Chui Tey5d2af632002-05-26 13:36:41 +0000946 if self.interp.rpcclt:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000947 dbg_gui = RemoteDebugger.start_remote_debugger(self.interp.rpcclt,
948 self)
949 else:
950 dbg_gui = Debugger.Debugger(self)
951 self.interp.setdebugger(dbg_gui)
952 dbg_gui.load_breakpoints()
Chui Tey5d2af632002-05-26 13:36:41 +0000953 sys.ps1 = "[DEBUG ON]\n>>> "
954 self.showprompt()
955 self.set_debugger_indicator()
956
David Scherer7aced172000-08-15 01:13:23 +0000957 def beginexecuting(self):
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000958 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +0000959 self.resetoutput()
960 self.executing = 1
David Scherer7aced172000-08-15 01:13:23 +0000961
962 def endexecuting(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000963 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +0000964 self.executing = 0
965 self.canceled = 0
Chui Tey5d2af632002-05-26 13:36:41 +0000966 self.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000967
968 def close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000969 "Extend EditorWindow.close()"
David Scherer7aced172000-08-15 01:13:23 +0000970 if self.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000971 response = tkMessageBox.askokcancel(
David Scherer7aced172000-08-15 01:13:23 +0000972 "Kill?",
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000973 "The program is still running!\n Do you want to kill it?",
David Scherer7aced172000-08-15 01:13:23 +0000974 default="ok",
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000975 parent=self.text)
Benjamin Peterson5b63acd2008-03-29 15:24:25 +0000976 if response is False:
David Scherer7aced172000-08-15 01:13:23 +0000977 return "cancel"
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +0000978 if self.reading:
979 self.top.quit()
980 self.canceled = True
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000981 self.closing = True
982 # Wait for poll_subprocess() rescheduling to stop
983 self.text.after(2 * self.pollinterval, self.close2)
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000984
985 def close2(self):
986 return EditorWindow.close(self)
David Scherer7aced172000-08-15 01:13:23 +0000987
988 def _close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000989 "Extend EditorWindow._close(), shut down debugger and execution server"
David Scherer7aced172000-08-15 01:13:23 +0000990 self.close_debugger()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000991 if use_subprocess:
992 self.interp.kill_subprocess()
David Scherer7aced172000-08-15 01:13:23 +0000993 # Restore std streams
994 sys.stdout = self.save_stdout
995 sys.stderr = self.save_stderr
996 sys.stdin = self.save_stdin
997 # Break cycles
998 self.interp = None
999 self.console = None
David Scherer7aced172000-08-15 01:13:23 +00001000 self.flist.pyshell = None
1001 self.history = None
Kurt B. Kaiser83118c62002-06-24 17:03:37 +00001002 EditorWindow._close(self)
David Scherer7aced172000-08-15 01:13:23 +00001003
1004 def ispythonsource(self, filename):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +00001005 "Override EditorWindow method: never remove the colorizer"
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001006 return True
David Scherer7aced172000-08-15 01:13:23 +00001007
1008 def short_title(self):
1009 return self.shell_title
1010
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +00001011 COPYRIGHT = \
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001012 'Type "copyright", "credits" or "license()" for more information.'
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +00001013
David Scherer7aced172000-08-15 01:13:23 +00001014 def begin(self):
1015 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001016 if use_subprocess:
1017 nosub = ''
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001018 client = self.interp.start_subprocess()
1019 if not client:
1020 self.close()
Kurt B. Kaiser76637292004-01-21 22:10:01 +00001021 return False
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001022 else:
1023 nosub = "==== No Subprocess ===="
Raymond Hettingerbf3f69e2009-01-26 23:29:09 +00001024 self.write("Python %s on %s\n%s\n%s" %
1025 (sys.version, sys.platform, self.COPYRIGHT, nosub))
David Scherer7aced172000-08-15 01:13:23 +00001026 self.showprompt()
Georg Brandl6634bf22008-05-20 07:13:37 +00001027 import Tkinter
1028 Tkinter._default_root = None # 03Jan04 KBK What's this?
Kurt B. Kaiser76637292004-01-21 22:10:01 +00001029 return True
David Scherer7aced172000-08-15 01:13:23 +00001030
1031 def readline(self):
1032 save = self.reading
1033 try:
1034 self.reading = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001035 self.top.mainloop() # nested mainloop()
David Scherer7aced172000-08-15 01:13:23 +00001036 finally:
1037 self.reading = save
1038 line = self.text.get("iomark", "end-1c")
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001039 if len(line) == 0: # may be EOF if we quit our mainloop with Ctrl-C
1040 line = "\n"
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001041 if isinstance(line, unicode):
Florent Xiclunad630c042010-04-02 07:24:52 +00001042 from idlelib import IOBinding
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001043 try:
1044 line = line.encode(IOBinding.encoding)
1045 except UnicodeError:
1046 pass
David Scherer7aced172000-08-15 01:13:23 +00001047 self.resetoutput()
1048 if self.canceled:
1049 self.canceled = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001050 if not use_subprocess:
1051 raise KeyboardInterrupt
David Scherer7aced172000-08-15 01:13:23 +00001052 if self.endoffile:
1053 self.endoffile = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001054 line = ""
David Scherer7aced172000-08-15 01:13:23 +00001055 return line
1056
1057 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001058 return True
David Scherer7aced172000-08-15 01:13:23 +00001059
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001060 def cancel_callback(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +00001061 try:
1062 if self.text.compare("sel.first", "!=", "sel.last"):
1063 return # Active selection -- always use default binding
1064 except:
1065 pass
1066 if not (self.executing or self.reading):
1067 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001068 self.interp.write("KeyboardInterrupt\n")
David Scherer7aced172000-08-15 01:13:23 +00001069 self.showprompt()
1070 return "break"
1071 self.endoffile = 0
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001072 self.canceled = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001073 if (self.executing and self.interp.rpcclt):
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +00001074 if self.interp.getdebugger():
1075 self.interp.restart_subprocess()
1076 else:
1077 self.interp.interrupt_subprocess()
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001078 if self.reading:
1079 self.top.quit() # exit the nested mainloop() in readline()
David Scherer7aced172000-08-15 01:13:23 +00001080 return "break"
1081
1082 def eof_callback(self, event):
1083 if self.executing and not self.reading:
1084 return # Let the default binding (delete next char) take over
1085 if not (self.text.compare("iomark", "==", "insert") and
1086 self.text.compare("insert", "==", "end-1c")):
1087 return # Let the default binding (delete next char) take over
1088 if not self.executing:
David Scherer7aced172000-08-15 01:13:23 +00001089 self.resetoutput()
1090 self.close()
1091 else:
1092 self.canceled = 0
1093 self.endoffile = 1
1094 self.top.quit()
1095 return "break"
1096
David Scherer7aced172000-08-15 01:13:23 +00001097 def linefeed_callback(self, event):
1098 # Insert a linefeed without entering anything (still autoindented)
1099 if self.reading:
1100 self.text.insert("insert", "\n")
1101 self.text.see("insert")
1102 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001103 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001104 return "break"
1105
1106 def enter_callback(self, event):
1107 if self.executing and not self.reading:
1108 return # Let the default binding (insert '\n') take over
1109 # If some text is selected, recall the selection
1110 # (but only if this before the I/O mark)
1111 try:
1112 sel = self.text.get("sel.first", "sel.last")
1113 if sel:
1114 if self.text.compare("sel.last", "<=", "iomark"):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001115 self.recall(sel, event)
David Scherer7aced172000-08-15 01:13:23 +00001116 return "break"
1117 except:
1118 pass
1119 # If we're strictly before the line containing iomark, recall
1120 # the current line, less a leading prompt, less leading or
1121 # trailing whitespace
1122 if self.text.compare("insert", "<", "iomark linestart"):
1123 # Check if there's a relevant stdin range -- if so, use it
1124 prev = self.text.tag_prevrange("stdin", "insert")
1125 if prev and self.text.compare("insert", "<", prev[1]):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001126 self.recall(self.text.get(prev[0], prev[1]), event)
David Scherer7aced172000-08-15 01:13:23 +00001127 return "break"
1128 next = self.text.tag_nextrange("stdin", "insert")
1129 if next and self.text.compare("insert lineend", ">=", next[0]):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001130 self.recall(self.text.get(next[0], next[1]), event)
David Scherer7aced172000-08-15 01:13:23 +00001131 return "break"
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001132 # No stdin mark -- just get the current line, less any prompt
Kurt B. Kaiserb1754452005-11-18 22:05:48 +00001133 indices = self.text.tag_nextrange("console", "insert linestart")
1134 if indices and \
1135 self.text.compare(indices[0], "<=", "insert linestart"):
1136 self.recall(self.text.get(indices[1], "insert lineend"), event)
1137 else:
1138 self.recall(self.text.get("insert linestart", "insert lineend"), event)
David Scherer7aced172000-08-15 01:13:23 +00001139 return "break"
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001140 # If we're between the beginning of the line and the iomark, i.e.
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001141 # in the prompt area, move to the end of the prompt
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001142 if self.text.compare("insert", "<", "iomark"):
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001143 self.text.mark_set("insert", "iomark")
David Scherer7aced172000-08-15 01:13:23 +00001144 # If we're in the current input and there's only whitespace
1145 # beyond the cursor, erase that whitespace first
1146 s = self.text.get("insert", "end-1c")
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001147 if s and not s.strip():
David Scherer7aced172000-08-15 01:13:23 +00001148 self.text.delete("insert", "end-1c")
1149 # If we're in the current input before its last line,
1150 # insert a newline right at the insert point
1151 if self.text.compare("insert", "<", "end-1c linestart"):
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001152 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001153 return "break"
1154 # We're in the last line; append a newline and submit it
1155 self.text.mark_set("insert", "end-1c")
1156 if self.reading:
1157 self.text.insert("insert", "\n")
1158 self.text.see("insert")
1159 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001160 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001161 self.text.tag_add("stdin", "iomark", "end-1c")
1162 self.text.update_idletasks()
1163 if self.reading:
1164 self.top.quit() # Break out of recursive mainloop() in raw_input()
1165 else:
1166 self.runit()
1167 return "break"
1168
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001169 def recall(self, s, event):
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001170 # remove leading and trailing empty or whitespace lines
1171 s = re.sub(r'^\s*\n', '' , s)
1172 s = re.sub(r'\n\s*$', '', s)
1173 lines = s.split('\n')
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001174 self.text.undo_block_start()
1175 try:
1176 self.text.tag_remove("sel", "1.0", "end")
1177 self.text.mark_set("insert", "end-1c")
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001178 prefix = self.text.get("insert linestart", "insert")
1179 if prefix.rstrip().endswith(':'):
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001180 self.newline_and_indent_event(event)
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001181 prefix = self.text.get("insert linestart", "insert")
1182 self.text.insert("insert", lines[0].strip())
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001183 if len(lines) > 1:
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001184 orig_base_indent = re.search(r'^([ \t]*)', lines[0]).group(0)
1185 new_base_indent = re.search(r'^([ \t]*)', prefix).group(0)
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001186 for line in lines[1:]:
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001187 if line.startswith(orig_base_indent):
1188 # replace orig base indentation with new indentation
1189 line = new_base_indent + line[len(orig_base_indent):]
1190 self.text.insert('insert', '\n'+line.rstrip())
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001191 finally:
1192 self.text.see("insert")
1193 self.text.undo_block_stop()
David Scherer7aced172000-08-15 01:13:23 +00001194
1195 def runit(self):
1196 line = self.text.get("iomark", "end-1c")
1197 # Strip off last newline and surrounding whitespace.
1198 # (To allow you to hit return twice to end a statement.)
1199 i = len(line)
1200 while i > 0 and line[i-1] in " \t":
1201 i = i-1
1202 if i > 0 and line[i-1] == "\n":
1203 i = i-1
1204 while i > 0 and line[i-1] in " \t":
1205 i = i-1
1206 line = line[:i]
1207 more = self.interp.runsource(line)
David Scherer7aced172000-08-15 01:13:23 +00001208
David Scherer7aced172000-08-15 01:13:23 +00001209 def open_stack_viewer(self, event=None):
Chui Tey5d2af632002-05-26 13:36:41 +00001210 if self.interp.rpcclt:
1211 return self.interp.remote_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +00001212 try:
1213 sys.last_traceback
1214 except:
1215 tkMessageBox.showerror("No stack trace",
1216 "There is no stack trace yet.\n"
1217 "(sys.last_traceback is not defined)",
1218 master=self.text)
1219 return
Florent Xiclunad630c042010-04-02 07:24:52 +00001220 from idlelib.StackViewer import StackBrowser
David Scherer7aced172000-08-15 01:13:23 +00001221 sv = StackBrowser(self.root, self.flist)
1222
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001223 def view_restart_mark(self, event=None):
1224 self.text.see("iomark")
1225 self.text.see("restart")
1226
1227 def restart_shell(self, event=None):
Terry Jan Reedyb98000a2012-01-31 02:09:25 -05001228 "Callback for Run/Restart Shell Cntl-F6"
1229 self.interp.restart_subprocess(with_cwd=True)
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001230
David Scherer7aced172000-08-15 01:13:23 +00001231 def showprompt(self):
1232 self.resetoutput()
1233 try:
1234 s = str(sys.ps1)
1235 except:
1236 s = ""
1237 self.console.write(s)
1238 self.text.mark_set("insert", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001239 self.set_line_and_column()
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +00001240 self.io.reset_undo()
David Scherer7aced172000-08-15 01:13:23 +00001241
1242 def resetoutput(self):
1243 source = self.text.get("iomark", "end-1c")
1244 if self.history:
1245 self.history.history_store(source)
1246 if self.text.get("end-2c") != "\n":
1247 self.text.insert("end-1c", "\n")
1248 self.text.mark_set("iomark", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001249 self.set_line_and_column()
David Scherer7aced172000-08-15 01:13:23 +00001250 sys.stdout.softspace = 0
1251
1252 def write(self, s, tags=()):
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001253 try:
1254 self.text.mark_gravity("iomark", "right")
1255 OutputWindow.write(self, s, tags, "iomark")
1256 self.text.mark_gravity("iomark", "left")
1257 except:
1258 pass
David Scherer7aced172000-08-15 01:13:23 +00001259 if self.canceled:
1260 self.canceled = 0
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001261 if not use_subprocess:
1262 raise KeyboardInterrupt
David Scherer7aced172000-08-15 01:13:23 +00001263
Kurt B. Kaiserdcba6622004-12-21 22:10:32 +00001264class PseudoFile(object):
David Scherer7aced172000-08-15 01:13:23 +00001265
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001266 def __init__(self, shell, tags, encoding=None):
David Scherer7aced172000-08-15 01:13:23 +00001267 self.shell = shell
1268 self.tags = tags
Chui Tey5d2af632002-05-26 13:36:41 +00001269 self.softspace = 0
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001270 self.encoding = encoding
David Scherer7aced172000-08-15 01:13:23 +00001271
1272 def write(self, s):
Terry Jan Reedyf8fc6742012-07-09 17:57:13 -04001273 if not isinstance(s, (basestring, bytearray)):
1274 raise TypeError('must be string, not ' + type(s).__name__)
David Scherer7aced172000-08-15 01:13:23 +00001275 self.shell.write(s, self.tags)
1276
Florent Xiclunad630c042010-04-02 07:24:52 +00001277 def writelines(self, lines):
1278 for line in lines:
1279 self.write(line)
David Scherer7aced172000-08-15 01:13:23 +00001280
1281 def flush(self):
1282 pass
1283
1284 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001285 return True
David Scherer7aced172000-08-15 01:13:23 +00001286
Martin v. Löwise2b56242012-07-25 10:56:22 +02001287class PseudoInputFile(object):
1288 def __init__(self, shell):
1289 self.readline = shell.readline
1290 self.isatty = shell.isatty
1291
1292 def write(self, s):
1293 raise io.UnsupportedOperation("not writable")
1294 writelines = write
1295
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001296
David Scherer7aced172000-08-15 01:13:23 +00001297usage_msg = """\
David Scherer7aced172000-08-15 01:13:23 +00001298
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001299USAGE: idle [-deins] [-t title] [file]*
1300 idle [-dns] [-t title] (-c cmd | -r file) [arg]*
1301 idle [-dns] [-t title] - [arg]*
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001302
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001303 -h print this help message and exit
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001304 -n run IDLE without a subprocess (see Help/IDLE Help for details)
David Scherer7aced172000-08-15 01:13:23 +00001305
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001306The following options will override the IDLE 'settings' configuration:
Kurt B. Kaiser96d88422001-07-17 04:59:01 +00001307
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001308 -e open an edit window
1309 -i open a shell window
1310
1311The following options imply -i and will open a shell:
1312
1313 -c cmd run the command in a shell, or
1314 -r file run script from file
1315
1316 -d enable the debugger
1317 -s run $IDLESTARTUP or $PYTHONSTARTUP before anything else
1318 -t title set title of shell window
1319
1320A default edit window will be bypassed when -c, -r, or - are used.
1321
1322[arg]* are passed to the command (-c) or script (-r) in sys.argv[1:].
1323
1324Examples:
1325
1326idle
1327 Open an edit window or shell depending on IDLE's configuration.
1328
1329idle foo.py foobar.py
1330 Edit the files, also open a shell if configured to start with shell.
1331
1332idle -est "Baz" foo.py
1333 Run $IDLESTARTUP or $PYTHONSTARTUP, edit foo.py, and open a shell
1334 window with the title "Baz".
1335
1336idle -c "import sys; print sys.argv" "foo"
1337 Open a shell window and run the command, passing "-c" in sys.argv[0]
1338 and "foo" in sys.argv[1].
1339
1340idle -d -s -r foo.py "Hello World"
1341 Open a shell window, run a startup script, enable the debugger, and
1342 run foo.py, passing "foo.py" in sys.argv[0] and "Hello World" in
1343 sys.argv[1].
1344
1345echo "import sys; print sys.argv" | idle - "foobar"
1346 Open a shell window, run the script piped in, passing '' in sys.argv[0]
1347 and "foobar" in sys.argv[1].
David Scherer7aced172000-08-15 01:13:23 +00001348"""
1349
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001350def main():
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001351 global flist, root, use_subprocess
David Scherer7aced172000-08-15 01:13:23 +00001352
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001353 use_subprocess = True
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +00001354 enable_shell = True
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001355 enable_edit = False
1356 debug = False
1357 cmd = None
1358 script = None
1359 startup = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001360 try:
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001361 opts, args = getopt.getopt(sys.argv[1:], "c:deihnr:st:")
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001362 except getopt.error, msg:
1363 sys.stderr.write("Error: %s\n" % str(msg))
1364 sys.stderr.write(usage_msg)
1365 sys.exit(2)
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001366 for o, a in opts:
1367 if o == '-c':
1368 cmd = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001369 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001370 if o == '-d':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001371 debug = True
1372 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001373 if o == '-e':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001374 enable_edit = True
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +00001375 enable_shell = False
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001376 if o == '-h':
1377 sys.stdout.write(usage_msg)
1378 sys.exit()
1379 if o == '-i':
1380 enable_shell = True
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001381 if o == '-n':
1382 use_subprocess = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001383 if o == '-r':
1384 script = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001385 if os.path.isfile(script):
1386 pass
1387 else:
1388 print "No script file: ", script
1389 sys.exit()
1390 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001391 if o == '-s':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001392 startup = True
1393 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001394 if o == '-t':
1395 PyShell.shell_title = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001396 enable_shell = True
1397 if args and args[0] == '-':
1398 cmd = sys.stdin.read()
1399 enable_shell = True
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001400 # process sys.argv and sys.path:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001401 for i in range(len(sys.path)):
1402 sys.path[i] = os.path.abspath(sys.path[i])
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001403 if args and args[0] == '-':
1404 sys.argv = [''] + args[1:]
1405 elif cmd:
1406 sys.argv = ['-c'] + args
1407 elif script:
1408 sys.argv = [script] + args
1409 elif args:
1410 enable_edit = True
1411 pathx = []
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001412 for filename in args:
1413 pathx.append(os.path.dirname(filename))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001414 for dir in pathx:
1415 dir = os.path.abspath(dir)
Florent Xiclunad630c042010-04-02 07:24:52 +00001416 if dir not in sys.path:
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001417 sys.path.insert(0, dir)
Kurt B. Kaiserff002b92002-12-21 21:39:11 +00001418 else:
1419 dir = os.getcwd()
1420 if not dir in sys.path:
1421 sys.path.insert(0, dir)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001422 # check the IDLE settings configuration (but command line overrides)
1423 edit_start = idleConf.GetOption('main', 'General',
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001424 'editor-on-startup', type='bool')
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001425 enable_edit = enable_edit or edit_start
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001426 # start editor and/or shell windows:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001427 root = Tk(className="Idle")
Ronald Oussoren19302d92006-06-11 14:33:36 +00001428
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001429 fixwordbreaks(root)
1430 root.withdraw()
1431 flist = PyShellFileList(root)
Ronald Oussoren19302d92006-06-11 14:33:36 +00001432 macosxSupport.setupApp(root, flist)
1433
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001434 if enable_edit:
1435 if not (cmd or script):
Andrew Svetlov7c010ee2012-03-21 13:35:08 +02001436 for filename in args[:]:
1437 if flist.open(filename) is None:
1438 # filename is a directory actually, disconsider it
1439 args.remove(filename)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001440 if not args:
1441 flist.new()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001442 if enable_shell:
Ronald Oussoren19302d92006-06-11 14:33:36 +00001443 shell = flist.open_shell()
1444 if not shell:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001445 return # couldn't open shell
Ronald Oussoren19302d92006-06-11 14:33:36 +00001446
1447 if macosxSupport.runningAsOSXApp() and flist.dict:
1448 # On OSX: when the user has double-clicked on a file that causes
Tim Peters4f96f1f2006-06-11 19:42:51 +00001449 # IDLE to be launched the shell window will open just in front of
1450 # the file she wants to see. Lower the interpreter window when
Ronald Oussoren19302d92006-06-11 14:33:36 +00001451 # there are open files.
1452 shell.top.lower()
1453
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001454 shell = flist.pyshell
1455 # handle remaining options:
1456 if debug:
1457 shell.open_debugger()
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001458 if startup:
1459 filename = os.environ.get("IDLESTARTUP") or \
1460 os.environ.get("PYTHONSTARTUP")
1461 if filename and os.path.isfile(filename):
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001462 shell.interp.execfile(filename)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001463 if shell and cmd or script:
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001464 shell.interp.runcommand("""if 1:
1465 import sys as _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001466 _sys.argv = %r
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001467 del _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001468 \n""" % (sys.argv,))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001469 if cmd:
1470 shell.interp.execsource(cmd)
1471 elif script:
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001472 shell.interp.prepend_syspath(script)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001473 shell.interp.execfile(script)
Ronald Oussoren19302d92006-06-11 14:33:36 +00001474
Ned Deily2a6f4b32011-01-30 00:18:47 +00001475 # Check for problematic OS X Tk versions and print a warning message
1476 # in the IDLE shell window; this is less intrusive than always opening
1477 # a separate window.
1478 tkversionwarning = macosxSupport.tkVersionWarning(root)
1479 if tkversionwarning:
1480 shell.interp.runcommand(''.join(("print('", tkversionwarning, "')")))
1481
Terry Jan Reedyeaa7e782012-05-26 20:33:32 -04001482 while flist.inversedict: # keep IDLE running while files are open.
1483 root.mainloop()
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001484 root.destroy()
1485
David Scherer7aced172000-08-15 01:13:23 +00001486if __name__ == "__main__":
Kurt B. Kaiser9e8b8282003-06-15 17:38:45 +00001487 sys.modules['PyShell'] = sys.modules['__main__']
David Scherer7aced172000-08-15 01:13:23 +00001488 main()