blob: 1e8629298b260dda301792f70f1130c051b66209 [file] [log] [blame]
David Scherer7aced172000-08-15 01:13:23 +00001#! /usr/bin/env python
2
David Scherer7aced172000-08-15 01:13:23 +00003import os
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +00004import os.path
David Scherer7aced172000-08-15 01:13:23 +00005import sys
6import string
7import getopt
8import re
Chui Tey5d2af632002-05-26 13:36:41 +00009import socket
10import time
Kurt B. Kaiser003091c2003-02-17 18:57:16 +000011import threading
Chui Tey5d2af632002-05-26 13:36:41 +000012import traceback
Kurt B. Kaiser62833982002-09-18 17:07:05 +000013import types
Martin v. Löwise2b56242012-07-25 10:56:22 +020014import io
David Scherer7aced172000-08-15 01:13:23 +000015
16import linecache
17from code import InteractiveInterpreter
Terry Jan Reedy4ade2d22014-02-08 09:39:51 -050018from platform import python_version, system
David Scherer7aced172000-08-15 01:13:23 +000019
Kurt B. Kaiser2303b1c2003-11-24 05:26:16 +000020try:
Georg Brandl6634bf22008-05-20 07:13:37 +000021 from Tkinter import *
Kurt B. Kaiser2303b1c2003-11-24 05:26:16 +000022except ImportError:
Georg Brandl6634bf22008-05-20 07:13:37 +000023 print>>sys.__stderr__, "** IDLE can't import Tkinter. " \
Kurt B. Kaiser2303b1c2003-11-24 05:26:16 +000024 "Your Python may not be configured for Tk. **"
25 sys.exit(1)
Georg Brandl6634bf22008-05-20 07:13:37 +000026import tkMessageBox
David Scherer7aced172000-08-15 01:13:23 +000027
Florent Xiclunad630c042010-04-02 07:24:52 +000028from idlelib.EditorWindow import EditorWindow, fixwordbreaks
29from idlelib.FileList import FileList
30from idlelib.ColorDelegator import ColorDelegator
31from idlelib.UndoDelegator import UndoDelegator
32from idlelib.OutputWindow import OutputWindow
33from idlelib.configHandler import idleConf
34from idlelib import idlever
35from idlelib import rpc
36from idlelib import Debugger
37from idlelib import RemoteDebugger
38from idlelib import macosxSupport
Chui Tey5d2af632002-05-26 13:36:41 +000039
Kurt B. Kaiserb9764192002-09-23 04:10:37 +000040IDENTCHARS = string.ascii_letters + string.digits + "_"
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +000041HOST = '127.0.0.1' # python execution server on localhost loopback
42PORT = 0 # someday pass in host, port for remote debug capability
Kurt B. Kaiserb9764192002-09-23 04:10:37 +000043
Kurt B. Kaisera00050f2003-05-08 20:26:55 +000044try:
45 from signal import SIGTERM
46except ImportError:
47 SIGTERM = 15
48
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000049# Override warnings module to write to warning_stream. Initialize to send IDLE
50# internal warnings to the console. ScriptBinding.check_syntax() will
51# temporarily redirect the stream to the shell window to display warnings when
52# checking user's code.
Terry Jan Reedy8eab0082013-06-28 23:51:34 -040053warning_stream = sys.__stderr__ # None, at least on Windows, if no console.
54import warnings
55
56def idle_formatwarning(message, category, filename, lineno, line=None):
57 """Format warnings the IDLE way."""
58
59 s = "\nWarning (from warnings module):\n"
60 s += ' File \"%s\", line %s\n' % (filename, lineno)
61 if line is None:
62 line = linecache.getline(filename, lineno)
63 line = line.strip()
64 if line:
65 s += " %s\n" % line
66 s += "%s: %s\n" % (category.__name__, message)
67 return s
68
69def idle_showwarning(
70 message, category, filename, lineno, file=None, line=None):
71 """Show Idle-format warning (after replacing warnings.showwarning).
72
73 The differences are the formatter called, the file=None replacement,
74 which can be None, the capture of the consequence AttributeError,
75 and the output of a hard-coded prompt.
76 """
77 if file is None:
78 file = warning_stream
79 try:
80 file.write(idle_formatwarning(
81 message, category, filename, lineno, line=line))
82 file.write(">>> ")
83 except (AttributeError, IOError):
84 pass # if file (probably __stderr__) is invalid, skip warning.
85
86_warnings_showwarning = None
87
88def capture_warnings(capture):
89 "Replace warning.showwarning with idle_showwarning, or reverse."
90
91 global _warnings_showwarning
92 if capture:
93 if _warnings_showwarning is None:
94 _warnings_showwarning = warnings.showwarning
95 warnings.showwarning = idle_showwarning
96 else:
97 if _warnings_showwarning is not None:
98 warnings.showwarning = _warnings_showwarning
99 _warnings_showwarning = None
100
101capture_warnings(True)
Chui Tey5d2af632002-05-26 13:36:41 +0000102
Kurt B. Kaiserf7a88992004-11-13 21:05:58 +0000103def extended_linecache_checkcache(filename=None,
104 orig_checkcache=linecache.checkcache):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000105 """Extend linecache.checkcache to preserve the <pyshell#...> entries
106
Kurt B. Kaiserf7a88992004-11-13 21:05:58 +0000107 Rather than repeating the linecache code, patch it to save the
108 <pyshell#...> entries, call the original linecache.checkcache()
Guilherme Polof198ac22009-08-14 14:03:07 +0000109 (skipping them), and then restore the saved entries.
Kurt B. Kaiserf7a88992004-11-13 21:05:58 +0000110
111 orig_checkcache is bound at definition time to the original
112 method, allowing it to be patched.
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000113 """
David Scherer7aced172000-08-15 01:13:23 +0000114 cache = linecache.cache
115 save = {}
Guilherme Polof198ac22009-08-14 14:03:07 +0000116 for key in list(cache):
117 if key[:1] + key[-1:] == '<>':
118 save[key] = cache.pop(key)
119 orig_checkcache(filename)
David Scherer7aced172000-08-15 01:13:23 +0000120 cache.update(save)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000121
Kurt B. Kaiser81885592002-11-29 22:10:53 +0000122# Patch linecache.checkcache():
123linecache.checkcache = extended_linecache_checkcache
David Scherer7aced172000-08-15 01:13:23 +0000124
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000125
David Scherer7aced172000-08-15 01:13:23 +0000126class PyShellEditorWindow(EditorWindow):
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000127 "Regular text edit window in IDLE, supports breakpoints"
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000128
David Scherer7aced172000-08-15 01:13:23 +0000129 def __init__(self, *args):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000130 self.breakpoints = []
Raymond Hettinger931237e2003-07-09 18:48:24 +0000131 EditorWindow.__init__(self, *args)
David Scherer7aced172000-08-15 01:13:23 +0000132 self.text.bind("<<set-breakpoint-here>>", self.set_breakpoint_here)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000133 self.text.bind("<<clear-breakpoint-here>>", self.clear_breakpoint_here)
David Scherer7aced172000-08-15 01:13:23 +0000134 self.text.bind("<<open-python-shell>>", self.flist.open_shell)
135
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000136 self.breakpointPath = os.path.join(idleConf.GetUserCfgDir(),
137 'breakpoints.lst')
Chui Teya2adb0f2002-11-04 22:14:54 +0000138 # whenever a file is changed, restore breakpoints
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000139 def filename_changed_hook(old_hook=self.io.filename_change_hook,
140 self=self):
Chui Teya2adb0f2002-11-04 22:14:54 +0000141 self.restore_file_breaks()
142 old_hook()
143 self.io.set_filename_change_hook(filename_changed_hook)
Roger Serwyd7c9d9c2013-04-02 22:37:12 -0500144 if self.io.filename:
145 self.restore_file_breaks()
Terry Jan Reedy25327d42014-08-08 23:33:11 -0400146 self.color_breakpoint_text()
Chui Teya2adb0f2002-11-04 22:14:54 +0000147
Andrew Svetlov5018db72012-11-01 22:39:14 +0200148 rmenu_specs = [
149 ("Cut", "<<cut>>", "rmenu_check_cut"),
150 ("Copy", "<<copy>>", "rmenu_check_copy"),
151 ("Paste", "<<paste>>", "rmenu_check_paste"),
152 ("Set Breakpoint", "<<set-breakpoint-here>>", None),
153 ("Clear Breakpoint", "<<clear-breakpoint-here>>", None)
154 ]
David Scherer7aced172000-08-15 01:13:23 +0000155
Terry Jan Reedy25327d42014-08-08 23:33:11 -0400156 def color_breakpoint_text(self, color=True):
157 "Turn colorizing of breakpoint text on or off"
158 if color:
159 theme = idleConf.GetOption('main','Theme','name')
160 cfg = idleConf.GetHighlight(theme, "break")
161 else:
162 cfg = {'foreground': '', 'background': ''}
163 self.text.tag_config('BREAK', cfg)
164
Chui Teya2adb0f2002-11-04 22:14:54 +0000165 def set_breakpoint(self, lineno):
166 text = self.text
167 filename = self.io.filename
168 text.tag_add("BREAK", "%d.0" % lineno, "%d.0" % (lineno+1))
169 try:
170 i = self.breakpoints.index(lineno)
171 except ValueError: # only add if missing, i.e. do once
172 self.breakpoints.append(lineno)
173 try: # update the subprocess debugger
174 debug = self.flist.pyshell.interp.debugger
175 debug.set_breakpoint_here(filename, lineno)
176 except: # but debugger may not be active right now....
177 pass
178
David Scherer7aced172000-08-15 01:13:23 +0000179 def set_breakpoint_here(self, event=None):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000180 text = self.text
181 filename = self.io.filename
182 if not filename:
183 text.bell()
David Scherer7aced172000-08-15 01:13:23 +0000184 return
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000185 lineno = int(float(text.index("insert")))
Chui Teya2adb0f2002-11-04 22:14:54 +0000186 self.set_breakpoint(lineno)
David Scherer7aced172000-08-15 01:13:23 +0000187
Kurt B. Kaiser669f4c32002-06-20 04:01:47 +0000188 def clear_breakpoint_here(self, event=None):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000189 text = self.text
190 filename = self.io.filename
191 if not filename:
192 text.bell()
Kurt B. Kaiser669f4c32002-06-20 04:01:47 +0000193 return
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000194 lineno = int(float(text.index("insert")))
195 try:
196 self.breakpoints.remove(lineno)
197 except:
198 pass
199 text.tag_remove("BREAK", "insert linestart",\
200 "insert lineend +1char")
201 try:
202 debug = self.flist.pyshell.interp.debugger
203 debug.clear_breakpoint_here(filename, lineno)
204 except:
205 pass
206
207 def clear_file_breaks(self):
208 if self.breakpoints:
209 text = self.text
210 filename = self.io.filename
211 if not filename:
212 text.bell()
213 return
214 self.breakpoints = []
215 text.tag_remove("BREAK", "1.0", END)
216 try:
217 debug = self.flist.pyshell.interp.debugger
218 debug.clear_file_breaks(filename)
219 except:
220 pass
221
Chui Teya2adb0f2002-11-04 22:14:54 +0000222 def store_file_breaks(self):
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000223 "Save breakpoints when file is saved"
224 # XXX 13 Dec 2002 KBK Currently the file must be saved before it can
225 # be run. The breaks are saved at that time. If we introduce
226 # a temporary file save feature the save breaks functionality
227 # needs to be re-verified, since the breaks at the time the
228 # temp file is created may differ from the breaks at the last
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000229 # permanent save of the file. Currently, a break introduced
230 # after a save will be effective, but not persistent.
231 # This is necessary to keep the saved breaks synched with the
232 # saved file.
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000233 #
234 # Breakpoints are set as tagged ranges in the text. Certain
235 # kinds of edits cause these ranges to be deleted: Inserting
236 # or deleting a line just before a breakpoint, and certain
237 # deletions prior to a breakpoint. These issues need to be
238 # investigated and understood. It's not clear if they are
239 # Tk issues or IDLE issues, or whether they can actually
240 # be fixed. Since a modified file has to be saved before it is
241 # run, and since self.breakpoints (from which the subprocess
242 # debugger is loaded) is updated during the save, the visible
243 # breaks stay synched with the subprocess even if one of these
244 # unexpected breakpoint deletions occurs.
245 breaks = self.breakpoints
246 filename = self.io.filename
Chui Teya2adb0f2002-11-04 22:14:54 +0000247 try:
Ned Deily40ad0412011-12-14 14:57:43 -0800248 with open(self.breakpointPath,"r") as old_file:
249 lines = old_file.readlines()
Chui Teya2adb0f2002-11-04 22:14:54 +0000250 except IOError:
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000251 lines = []
Ned Deily40ad0412011-12-14 14:57:43 -0800252 try:
253 with open(self.breakpointPath,"w") as new_file:
254 for line in lines:
255 if not line.startswith(filename + '='):
256 new_file.write(line)
257 self.update_breakpoints()
258 breaks = self.breakpoints
259 if breaks:
260 new_file.write(filename + '=' + str(breaks) + '\n')
261 except IOError as err:
262 if not getattr(self.root, "breakpoint_error_displayed", False):
263 self.root.breakpoint_error_displayed = True
264 tkMessageBox.showerror(title='IDLE Error',
265 message='Unable to update breakpoint list:\n%s'
266 % str(err),
267 parent=self.text)
Chui Teya2adb0f2002-11-04 22:14:54 +0000268
269 def restore_file_breaks(self):
270 self.text.update() # this enables setting "BREAK" tags to be visible
Roger Serwyd7c9d9c2013-04-02 22:37:12 -0500271 if self.io is None:
272 # can happen if IDLE closes due to the .update() call
273 return
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000274 filename = self.io.filename
275 if filename is None:
276 return
Chui Tey69371d62002-11-04 23:39:45 +0000277 if os.path.isfile(self.breakpointPath):
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000278 lines = open(self.breakpointPath,"r").readlines()
Chui Tey69371d62002-11-04 23:39:45 +0000279 for line in lines:
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000280 if line.startswith(filename + '='):
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000281 breakpoint_linenumbers = eval(line[len(filename)+1:])
Chui Tey69371d62002-11-04 23:39:45 +0000282 for breakpoint_linenumber in breakpoint_linenumbers:
283 self.set_breakpoint(breakpoint_linenumber)
Chui Teya2adb0f2002-11-04 22:14:54 +0000284
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000285 def update_breakpoints(self):
286 "Retrieves all the breakpoints in the current window"
Chui Teya2adb0f2002-11-04 22:14:54 +0000287 text = self.text
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000288 ranges = text.tag_ranges("BREAK")
289 linenumber_list = self.ranges_to_linenumbers(ranges)
290 self.breakpoints = linenumber_list
291
292 def ranges_to_linenumbers(self, ranges):
293 lines = []
294 for index in range(0, len(ranges), 2):
Andrew Svetlov8a15c372012-07-31 19:51:27 +0300295 lineno = int(float(ranges[index].string))
296 end = int(float(ranges[index+1].string))
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000297 while lineno < end:
298 lines.append(lineno)
299 lineno += 1
300 return lines
301
Kurt B. Kaiser11220fa2002-12-24 00:57:22 +0000302# XXX 13 Dec 2002 KBK Not used currently
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000303# def saved_change_hook(self):
304# "Extend base method - clear breaks if module is modified"
305# if not self.get_saved():
306# self.clear_file_breaks()
307# EditorWindow.saved_change_hook(self)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000308
309 def _close(self):
310 "Extend base method - clear breaks when module is closed"
311 self.clear_file_breaks()
312 EditorWindow._close(self)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000313
David Scherer7aced172000-08-15 01:13:23 +0000314
315class PyShellFileList(FileList):
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000316 "Extend base class: IDLE supports a shell and breakpoints"
David Scherer7aced172000-08-15 01:13:23 +0000317
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000318 # override FileList's class variable, instances return PyShellEditorWindow
319 # instead of EditorWindow when new edit windows are created.
David Scherer7aced172000-08-15 01:13:23 +0000320 EditorWindow = PyShellEditorWindow
321
322 pyshell = None
323
324 def open_shell(self, event=None):
325 if self.pyshell:
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000326 self.pyshell.top.wakeup()
David Scherer7aced172000-08-15 01:13:23 +0000327 else:
328 self.pyshell = PyShell(self)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000329 if self.pyshell:
330 if not self.pyshell.begin():
331 return None
David Scherer7aced172000-08-15 01:13:23 +0000332 return self.pyshell
333
334
335class ModifiedColorDelegator(ColorDelegator):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000336 "Extend base class: colorizer for the shell window itself"
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000337
Steven M. Gavab77d3432002-03-02 07:16:21 +0000338 def __init__(self):
339 ColorDelegator.__init__(self)
340 self.LoadTagDefs()
David Scherer7aced172000-08-15 01:13:23 +0000341
342 def recolorize_main(self):
343 self.tag_remove("TODO", "1.0", "iomark")
344 self.tag_add("SYNC", "1.0", "iomark")
345 ColorDelegator.recolorize_main(self)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000346
Steven M. Gavab77d3432002-03-02 07:16:21 +0000347 def LoadTagDefs(self):
348 ColorDelegator.LoadTagDefs(self)
349 theme = idleConf.GetOption('main','Theme','name')
350 self.tagdefs.update({
351 "stdin": {'background':None,'foreground':None},
352 "stdout": idleConf.GetHighlight(theme, "stdout"),
353 "stderr": idleConf.GetHighlight(theme, "stderr"),
354 "console": idleConf.GetHighlight(theme, "console"),
Steven M. Gavab77d3432002-03-02 07:16:21 +0000355 })
David Scherer7aced172000-08-15 01:13:23 +0000356
Ned Deily5e247b72012-05-31 09:17:29 -0700357 def removecolors(self):
358 # Don't remove shell color tags before "iomark"
359 for tag in self.tagdefs:
360 self.tag_remove(tag, "iomark", "end")
361
David Scherer7aced172000-08-15 01:13:23 +0000362class ModifiedUndoDelegator(UndoDelegator):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000363 "Extend base class: forbid insert/delete before the I/O mark"
David Scherer7aced172000-08-15 01:13:23 +0000364
365 def insert(self, index, chars, tags=None):
366 try:
367 if self.delegate.compare(index, "<", "iomark"):
368 self.delegate.bell()
369 return
370 except TclError:
371 pass
372 UndoDelegator.insert(self, index, chars, tags)
373
374 def delete(self, index1, index2=None):
375 try:
376 if self.delegate.compare(index1, "<", "iomark"):
377 self.delegate.bell()
378 return
379 except TclError:
380 pass
381 UndoDelegator.delete(self, index1, index2)
382
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000383
384class MyRPCClient(rpc.RPCClient):
385
386 def handle_EOF(self):
387 "Override the base class - just re-raise EOFError"
388 raise EOFError
389
Kurt B. Kaiser8d1f11b2003-05-26 22:20:34 +0000390
David Scherer7aced172000-08-15 01:13:23 +0000391class ModifiedInterpreter(InteractiveInterpreter):
392
393 def __init__(self, tkconsole):
394 self.tkconsole = tkconsole
395 locals = sys.modules['__main__'].__dict__
396 InteractiveInterpreter.__init__(self, locals=locals)
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000397 self.save_warnings_filters = None
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000398 self.restarting = False
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +0000399 self.subprocess_arglist = None
400 self.port = PORT
Ned Deily86d669b2011-10-30 19:58:04 -0700401 self.original_compiler_flags = self.compile.compiler.flags
David Scherer7aced172000-08-15 01:13:23 +0000402
Roger Serwy16ce43a2013-06-11 22:13:17 -0500403 _afterid = None
Chui Tey5d2af632002-05-26 13:36:41 +0000404 rpcclt = None
405 rpcpid = None
406
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000407 def spawn_subprocess(self):
Florent Xiclunac8a730b2010-03-25 20:32:07 +0000408 if self.subprocess_arglist is None:
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +0000409 self.subprocess_arglist = self.build_subprocess_arglist()
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000410 args = self.subprocess_arglist
Kurt B. Kaiserb7855182003-08-14 14:54:28 +0000411 self.rpcpid = os.spawnv(os.P_NOWAIT, sys.executable, args)
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000412
Tony Lowndsf53dec22002-12-20 04:24:43 +0000413 def build_subprocess_arglist(self):
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +0000414 assert (self.port!=0), (
415 "Socket should have been assigned a port number.")
Tony Lownds2398d572003-05-13 15:28:21 +0000416 w = ['-W' + s for s in sys.warnoptions]
Georg Brandld0761532006-10-12 07:57:21 +0000417 if 1/2 > 0: # account for new division
418 w.append('-Qnew')
Tony Lownds2398d572003-05-13 15:28:21 +0000419 # Maybe IDLE is installed and is being accessed via sys.path,
420 # or maybe it's not installed and the idle.py script is being
421 # run from the IDLE source directory.
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000422 del_exitf = idleConf.GetOption('main', 'General', 'delete-exitfunc',
423 default=False, type='bool')
Tony Lownds2398d572003-05-13 15:28:21 +0000424 if __name__ == 'idlelib.PyShell':
Walter Dörwald70a6b492004-02-12 17:35:32 +0000425 command = "__import__('idlelib.run').run.main(%r)" % (del_exitf,)
Tony Lowndsf2324b92002-09-29 00:34:10 +0000426 else:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000427 command = "__import__('run').main(%r)" % (del_exitf,)
Kurt B. Kaiserb7855182003-08-14 14:54:28 +0000428 if sys.platform[:3] == 'win' and ' ' in sys.executable:
429 # handle embedded space in path by quoting the argument
430 decorated_exec = '"%s"' % sys.executable
431 else:
432 decorated_exec = sys.executable
433 return [decorated_exec] + w + ["-c", command, str(self.port)]
Tony Lowndsf2324b92002-09-29 00:34:10 +0000434
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000435 def start_subprocess(self):
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +0000436 addr = (HOST, self.port)
437 # GUI makes several attempts to acquire socket, listens for connection
Kurt B. Kaiser5db48432003-05-15 03:40:51 +0000438 for i in range(3):
Chui Tey5d2af632002-05-26 13:36:41 +0000439 time.sleep(i)
440 try:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000441 self.rpcclt = MyRPCClient(addr)
Chui Tey5d2af632002-05-26 13:36:41 +0000442 break
Terry Jan Reedy2b149862013-06-29 00:59:34 -0400443 except socket.error as err:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000444 pass
Chui Tey5d2af632002-05-26 13:36:41 +0000445 else:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000446 self.display_port_binding_error()
447 return None
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +0000448 # if PORT was 0, system will assign an 'ephemeral' port. Find it out:
449 self.port = self.rpcclt.listening_sock.getsockname()[1]
450 # if PORT was not 0, probably working with a remote execution server
451 if PORT != 0:
452 # To allow reconnection within the 2MSL wait (cf. Stevens TCP
453 # V1, 18.6), set SO_REUSEADDR. Note that this can be problematic
454 # on Windows since the implementation allows two active sockets on
455 # the same address!
456 self.rpcclt.listening_sock.setsockopt(socket.SOL_SOCKET,
457 socket.SO_REUSEADDR, 1)
458 self.spawn_subprocess()
459 #time.sleep(20) # test to simulate GUI not accepting connection
Kurt B. Kaiserb4179362002-07-26 00:06:42 +0000460 # Accept the connection from the Python execution server
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000461 self.rpcclt.listening_sock.settimeout(10)
462 try:
463 self.rpcclt.accept()
Terry Jan Reedy2b149862013-06-29 00:59:34 -0400464 except socket.timeout as err:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000465 self.display_no_subprocess_error()
466 return None
Serhiy Storchaka9abc8302013-01-25 15:30:35 +0200467 self.rpcclt.register("console", self.tkconsole)
468 self.rpcclt.register("stdin", self.tkconsole.stdin)
Kurt B. Kaiser969de452002-06-12 03:28:57 +0000469 self.rpcclt.register("stdout", self.tkconsole.stdout)
470 self.rpcclt.register("stderr", self.tkconsole.stderr)
Chui Tey5d2af632002-05-26 13:36:41 +0000471 self.rpcclt.register("flist", self.tkconsole.flist)
Kurt B. Kaiser8cd0def2003-01-31 05:06:43 +0000472 self.rpcclt.register("linecache", linecache)
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000473 self.rpcclt.register("interp", self)
Terry Jan Reedyb98000a2012-01-31 02:09:25 -0500474 self.transfer_path(with_cwd=True)
Chui Tey5d2af632002-05-26 13:36:41 +0000475 self.poll_subprocess()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000476 return self.rpcclt
Chui Tey5d2af632002-05-26 13:36:41 +0000477
Terry Jan Reedyb98000a2012-01-31 02:09:25 -0500478 def restart_subprocess(self, with_cwd=False):
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000479 if self.restarting:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000480 return self.rpcclt
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000481 self.restarting = True
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000482 # close only the subprocess debugger
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000483 debug = self.getdebugger()
484 if debug:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000485 try:
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000486 # Only close subprocess debugger, don't unregister gui_adap!
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000487 RemoteDebugger.close_subprocess_debugger(self.rpcclt)
488 except:
489 pass
490 # Kill subprocess, spawn a new one, accept connection.
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000491 self.rpcclt.close()
492 self.unix_terminate()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000493 console = self.tkconsole
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000494 was_executing = console.executing
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000495 console.executing = False
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000496 self.spawn_subprocess()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000497 try:
498 self.rpcclt.accept()
Terry Jan Reedy2b149862013-06-29 00:59:34 -0400499 except socket.timeout as err:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000500 self.display_no_subprocess_error()
501 return None
Terry Jan Reedyb98000a2012-01-31 02:09:25 -0500502 self.transfer_path(with_cwd=with_cwd)
Roger Serwyad8cad32013-04-03 00:42:24 -0500503 console.stop_readline()
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000504 # annotate restart in shell window and mark it
Kurt B. Kaiser4cc5ef52003-01-22 00:23:23 +0000505 console.text.delete("iomark", "end-1c")
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000506 if was_executing:
507 console.write('\n')
508 console.showprompt()
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000509 halfbar = ((int(console.width) - 16) // 2) * '='
510 console.write(halfbar + ' RESTART ' + halfbar)
511 console.text.mark_set("restart", "end-1c")
512 console.text.mark_gravity("restart", "left")
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000513 console.showprompt()
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000514 # restart subprocess debugger
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000515 if debug:
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000516 # Restarted debugger connects to current instance of debug GUI
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000517 gui = RemoteDebugger.restart_subprocess_debugger(self.rpcclt)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000518 # reload remote debugger breakpoints for all PyShellEditWindows
519 debug.load_breakpoints()
Ned Deily86d669b2011-10-30 19:58:04 -0700520 self.compile.compiler.flags = self.original_compiler_flags
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000521 self.restarting = False
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000522 return self.rpcclt
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000523
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000524 def __request_interrupt(self):
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000525 self.rpcclt.remotecall("exec", "interrupt_the_server", (), {})
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000526
527 def interrupt_subprocess(self):
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000528 threading.Thread(target=self.__request_interrupt).start()
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000529
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000530 def kill_subprocess(self):
Roger Serwy16ce43a2013-06-11 22:13:17 -0500531 if self._afterid is not None:
532 self.tkconsole.text.after_cancel(self._afterid)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000533 try:
534 self.rpcclt.close()
535 except AttributeError: # no socket
536 pass
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000537 self.unix_terminate()
538 self.tkconsole.executing = False
539 self.rpcclt = None
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000540
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000541 def unix_terminate(self):
542 "UNIX: make sure subprocess is terminated and collect status"
543 if hasattr(os, 'kill'):
544 try:
545 os.kill(self.rpcpid, SIGTERM)
546 except OSError:
547 # process already terminated:
548 return
549 else:
550 try:
551 os.waitpid(self.rpcpid, 0)
552 except OSError:
553 return
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000554
Terry Jan Reedyb98000a2012-01-31 02:09:25 -0500555 def transfer_path(self, with_cwd=False):
556 if with_cwd: # Issue 13506
557 path = [''] # include Current Working Directory
558 path.extend(sys.path)
559 else:
560 path = sys.path
Terry Jan Reedy1d4ae482012-01-31 02:55:32 -0500561
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000562 self.runcommand("""if 1:
563 import sys as _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +0000564 _sys.path = %r
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000565 del _sys
Terry Jan Reedyb98000a2012-01-31 02:09:25 -0500566 \n""" % (path,))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000567
Chui Tey5d2af632002-05-26 13:36:41 +0000568 active_seq = None
569
570 def poll_subprocess(self):
571 clt = self.rpcclt
572 if clt is None:
573 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000574 try:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000575 response = clt.pollresponse(self.active_seq, wait=0.05)
576 except (EOFError, IOError, KeyboardInterrupt):
577 # lost connection or subprocess terminated itself, restart
578 # [the KBI is from rpc.SocketIO.handle_EOF()]
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000579 if self.tkconsole.closing:
580 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000581 response = None
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000582 self.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000583 if response:
584 self.tkconsole.resetoutput()
585 self.active_seq = None
586 how, what = response
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000587 console = self.tkconsole.console
Chui Tey5d2af632002-05-26 13:36:41 +0000588 if how == "OK":
589 if what is not None:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000590 print >>console, repr(what)
Chui Tey5d2af632002-05-26 13:36:41 +0000591 elif how == "EXCEPTION":
Chui Tey5d2af632002-05-26 13:36:41 +0000592 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
593 self.remote_stack_viewer()
594 elif how == "ERROR":
Kurt B. Kaiser0930c432002-12-06 21:45:24 +0000595 errmsg = "PyShell.ModifiedInterpreter: Subprocess ERROR:\n"
596 print >>sys.__stderr__, errmsg, what
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000597 print >>console, errmsg, what
598 # we received a response to the currently active seq number:
Kurt B. Kaiserd112bc72006-08-16 05:01:42 +0000599 try:
600 self.tkconsole.endexecuting()
601 except AttributeError: # shell may have closed
602 pass
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000603 # Reschedule myself
604 if not self.tkconsole.closing:
Roger Serwy16ce43a2013-06-11 22:13:17 -0500605 self._afterid = self.tkconsole.text.after(
606 self.tkconsole.pollinterval, self.poll_subprocess)
Chui Tey5d2af632002-05-26 13:36:41 +0000607
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000608 debugger = None
609
610 def setdebugger(self, debugger):
611 self.debugger = debugger
612
613 def getdebugger(self):
614 return self.debugger
615
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000616 def open_remote_stack_viewer(self):
617 """Initiate the remote stack viewer from a separate thread.
618
619 This method is called from the subprocess, and by returning from this
620 method we allow the subprocess to unblock. After a bit the shell
621 requests the subprocess to open the remote stack viewer which returns a
Ezio Melottic569cfe2010-07-23 16:55:21 +0000622 static object looking at the last exception. It is queried through
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000623 the RPC mechanism.
624
625 """
626 self.tkconsole.text.after(300, self.remote_stack_viewer)
627 return
628
Chui Tey5d2af632002-05-26 13:36:41 +0000629 def remote_stack_viewer(self):
Florent Xiclunad630c042010-04-02 07:24:52 +0000630 from idlelib import RemoteObjectBrowser
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000631 oid = self.rpcclt.remotequeue("exec", "stackviewer", ("flist",), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000632 if oid is None:
633 self.tkconsole.root.bell()
634 return
635 item = RemoteObjectBrowser.StubObjectTreeItem(self.rpcclt, oid)
Florent Xiclunad630c042010-04-02 07:24:52 +0000636 from idlelib.TreeWidget import ScrolledCanvas, TreeNode
Chui Tey5d2af632002-05-26 13:36:41 +0000637 top = Toplevel(self.tkconsole.root)
Kurt B. Kaiser73360a32004-03-08 18:15:31 +0000638 theme = idleConf.GetOption('main','Theme','name')
639 background = idleConf.GetHighlight(theme, 'normal')['background']
640 sc = ScrolledCanvas(top, bg=background, highlightthickness=0)
Chui Tey5d2af632002-05-26 13:36:41 +0000641 sc.frame.pack(expand=1, fill="both")
642 node = TreeNode(sc.canvas, None, item)
643 node.expand()
644 # XXX Should GC the remote tree when closing the window
645
David Scherer7aced172000-08-15 01:13:23 +0000646 gid = 0
647
648 def execsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000649 "Like runsource() but assumes complete exec source"
David Scherer7aced172000-08-15 01:13:23 +0000650 filename = self.stuffsource(source)
651 self.execfile(filename, source)
652
653 def execfile(self, filename, source=None):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000654 "Execute an existing file"
David Scherer7aced172000-08-15 01:13:23 +0000655 if source is None:
656 source = open(filename, "r").read()
657 try:
658 code = compile(source, filename, "exec")
659 except (OverflowError, SyntaxError):
660 self.tkconsole.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000661 tkerr = self.tkconsole.stderr
662 print>>tkerr, '*** Error in script or command!\n'
663 print>>tkerr, 'Traceback (most recent call last):'
David Scherer7aced172000-08-15 01:13:23 +0000664 InteractiveInterpreter.showsyntaxerror(self, filename)
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000665 self.tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000666 else:
667 self.runcode(code)
668
669 def runsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000670 "Extend base class method: Stuff the source in the line cache first"
David Scherer7aced172000-08-15 01:13:23 +0000671 filename = self.stuffsource(source)
672 self.more = 0
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000673 self.save_warnings_filters = warnings.filters[:]
674 warnings.filterwarnings(action="error", category=SyntaxWarning)
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000675 if isinstance(source, types.UnicodeType):
Florent Xiclunad630c042010-04-02 07:24:52 +0000676 from idlelib import IOBinding
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000677 try:
678 source = source.encode(IOBinding.encoding)
679 except UnicodeError:
680 self.tkconsole.resetoutput()
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +0000681 self.write("Unsupported characters in input\n")
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000682 return
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000683 try:
Kurt B. Kaiser935ea9a2005-05-10 03:44:24 +0000684 # InteractiveInterpreter.runsource() calls its runcode() method,
685 # which is overridden (see below)
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000686 return InteractiveInterpreter.runsource(self, source, filename)
687 finally:
688 if self.save_warnings_filters is not None:
689 warnings.filters[:] = self.save_warnings_filters
690 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000691
692 def stuffsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000693 "Stuff source in the filename cache"
David Scherer7aced172000-08-15 01:13:23 +0000694 filename = "<pyshell#%d>" % self.gid
695 self.gid = self.gid + 1
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000696 lines = source.split("\n")
David Scherer7aced172000-08-15 01:13:23 +0000697 linecache.cache[filename] = len(source)+1, 0, lines, filename
698 return filename
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000699
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000700 def prepend_syspath(self, filename):
701 "Prepend sys.path with file's directory if not already included"
702 self.runcommand("""if 1:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000703 _filename = %r
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000704 import sys as _sys
705 from os.path import dirname as _dirname
706 _dir = _dirname(_filename)
707 if not _dir in _sys.path:
708 _sys.path.insert(0, _dir)
709 del _filename, _sys, _dirname, _dir
Walter Dörwald70a6b492004-02-12 17:35:32 +0000710 \n""" % (filename,))
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000711
David Scherer7aced172000-08-15 01:13:23 +0000712 def showsyntaxerror(self, filename=None):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000713 """Extend base class method: Add Colorizing
714
715 Color the offending position instead of printing it and pointing at it
716 with a caret.
717
718 """
David Scherer7aced172000-08-15 01:13:23 +0000719 text = self.tkconsole.text
720 stuff = self.unpackerror()
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000721 if stuff:
722 msg, lineno, offset, line = stuff
723 if lineno == 1:
724 pos = "iomark + %d chars" % (offset-1)
725 else:
726 pos = "iomark linestart + %d lines + %d chars" % \
727 (lineno-1, offset-1)
728 text.tag_add("ERROR", pos)
729 text.see(pos)
730 char = text.get(pos)
731 if char and char in IDENTCHARS:
732 text.tag_add("ERROR", pos + " wordstart", pos)
733 self.tkconsole.resetoutput()
734 self.write("SyntaxError: %s\n" % str(msg))
735 else:
David Scherer7aced172000-08-15 01:13:23 +0000736 self.tkconsole.resetoutput()
737 InteractiveInterpreter.showsyntaxerror(self, filename)
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000738 self.tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000739
740 def unpackerror(self):
741 type, value, tb = sys.exc_info()
742 ok = type is SyntaxError
743 if ok:
744 try:
745 msg, (dummy_filename, lineno, offset, line) = value
Kurt B. Kaiserbea57c62003-07-09 04:27:24 +0000746 if not offset:
747 offset = 0
David Scherer7aced172000-08-15 01:13:23 +0000748 except:
749 ok = 0
750 if ok:
751 return msg, lineno, offset, line
752 else:
753 return None
754
755 def showtraceback(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000756 "Extend base class method to reset output properly"
David Scherer7aced172000-08-15 01:13:23 +0000757 self.tkconsole.resetoutput()
758 self.checklinecache()
759 InteractiveInterpreter.showtraceback(self)
Chui Tey5d2af632002-05-26 13:36:41 +0000760 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
761 self.tkconsole.open_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +0000762
763 def checklinecache(self):
764 c = linecache.cache
765 for key in c.keys():
766 if key[:1] + key[-1:] != "<>":
767 del c[key]
768
Chui Tey5d2af632002-05-26 13:36:41 +0000769 def runcommand(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000770 "Run the code without invoking the debugger"
Chui Tey5d2af632002-05-26 13:36:41 +0000771 # The code better not raise an exception!
772 if self.tkconsole.executing:
Neal Norwitzf4c4f112002-11-30 18:49:10 +0000773 self.display_executing_dialog()
Chui Tey5d2af632002-05-26 13:36:41 +0000774 return 0
775 if self.rpcclt:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000776 self.rpcclt.remotequeue("exec", "runcode", (code,), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000777 else:
778 exec code in self.locals
779 return 1
780
David Scherer7aced172000-08-15 01:13:23 +0000781 def runcode(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000782 "Override base class method"
Chui Tey5d2af632002-05-26 13:36:41 +0000783 if self.tkconsole.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000784 self.interp.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000785 self.checklinecache()
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000786 if self.save_warnings_filters is not None:
787 warnings.filters[:] = self.save_warnings_filters
788 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000789 debugger = self.debugger
790 try:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000791 self.tkconsole.beginexecuting()
Kurt B. Kaiserdddeb0e2007-02-06 03:21:40 +0000792 if not debugger and self.rpcclt is not None:
793 self.active_seq = self.rpcclt.asyncqueue("exec", "runcode",
794 (code,), {})
795 elif debugger:
796 debugger.run(code, self.locals)
797 else:
798 exec code in self.locals
799 except SystemExit:
800 if not self.tkconsole.closing:
801 if tkMessageBox.askyesno(
802 "Exit?",
803 "Do you want to exit altogether?",
804 default="yes",
805 master=self.tkconsole.text):
Kurt B. Kaiserf137e1d2006-08-16 07:04:17 +0000806 raise
Kurt B. Kaiserdddeb0e2007-02-06 03:21:40 +0000807 else:
808 self.showtraceback()
809 else:
810 raise
811 except:
812 if use_subprocess:
813 print >>self.tkconsole.stderr, \
814 "IDLE internal error in runcode()"
David Scherer7aced172000-08-15 01:13:23 +0000815 self.showtraceback()
Kurt B. Kaiserdddeb0e2007-02-06 03:21:40 +0000816 self.tkconsole.endexecuting()
817 else:
818 if self.tkconsole.canceled:
819 self.tkconsole.canceled = False
820 print >>self.tkconsole.stderr, "KeyboardInterrupt"
821 else:
822 self.showtraceback()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000823 finally:
824 if not use_subprocess:
Kurt B. Kaiserd112bc72006-08-16 05:01:42 +0000825 try:
826 self.tkconsole.endexecuting()
827 except AttributeError: # shell may have closed
828 pass
David Scherer7aced172000-08-15 01:13:23 +0000829
830 def write(self, s):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000831 "Override base class method"
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000832 self.tkconsole.stderr.write(s)
David Scherer7aced172000-08-15 01:13:23 +0000833
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000834 def display_port_binding_error(self):
835 tkMessageBox.showerror(
836 "Port Binding Error",
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +0000837 "IDLE can't bind to a TCP/IP port, which is necessary to "
838 "communicate with its Python execution server. This might be "
839 "because no networking is installed on this computer. "
840 "Run IDLE with the -n command line switch to start without a "
841 "subprocess and refer to Help/IDLE Help 'Running without a "
842 "subprocess' for further details.",
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000843 master=self.tkconsole.text)
844
845 def display_no_subprocess_error(self):
846 tkMessageBox.showerror(
847 "Subprocess Startup Error",
848 "IDLE's subprocess didn't make connection. Either IDLE can't "
849 "start a subprocess or personal firewall software is blocking "
850 "the connection.",
851 master=self.tkconsole.text)
852
853 def display_executing_dialog(self):
854 tkMessageBox.showerror(
855 "Already executing",
856 "The Python Shell window is already executing a command; "
857 "please wait until it is finished.",
858 master=self.tkconsole.text)
859
860
David Scherer7aced172000-08-15 01:13:23 +0000861class PyShell(OutputWindow):
862
Terry Jan Reedyd676a3a2013-03-30 18:50:43 -0400863 shell_title = "Python " + python_version() + " Shell"
David Scherer7aced172000-08-15 01:13:23 +0000864
865 # Override classes
866 ColorDelegator = ModifiedColorDelegator
867 UndoDelegator = ModifiedUndoDelegator
868
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000869 # Override menus
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000870 menu_specs = [
871 ("file", "_File"),
872 ("edit", "_Edit"),
Kurt B. Kaiser4cc5ef52003-01-22 00:23:23 +0000873 ("debug", "_Debug"),
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000874 ("options", "_Options"),
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000875 ("windows", "_Windows"),
876 ("help", "_Help"),
877 ]
David Scherer7aced172000-08-15 01:13:23 +0000878
Ned Deily57847df2014-03-27 20:47:04 -0700879 if sys.platform == "darwin":
Ronald Oussoren19302d92006-06-11 14:33:36 +0000880 menu_specs[-2] = ("windows", "_Window")
881
882
David Scherer7aced172000-08-15 01:13:23 +0000883 # New classes
Florent Xiclunad630c042010-04-02 07:24:52 +0000884 from idlelib.IdleHistory import History
David Scherer7aced172000-08-15 01:13:23 +0000885
886 def __init__(self, flist=None):
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000887 if use_subprocess:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000888 ms = self.menu_specs
889 if ms[2][0] != "shell":
Kurt B. Kaiser7ae35482006-08-16 21:45:59 +0000890 ms.insert(2, ("shell", "She_ll"))
David Scherer7aced172000-08-15 01:13:23 +0000891 self.interp = ModifiedInterpreter(self)
892 if flist is None:
893 root = Tk()
894 fixwordbreaks(root)
895 root.withdraw()
896 flist = PyShellFileList(root)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000897 #
David Scherer7aced172000-08-15 01:13:23 +0000898 OutputWindow.__init__(self, flist, None, None)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000899 #
Kurt B. Kaiser6af44982005-01-19 00:22:59 +0000900## self.config(usetabs=1, indentwidth=8, context_use_ps1=1)
901 self.usetabs = True
902 # indentwidth must be 8 when using tabs. See note in EditorWindow:
903 self.indentwidth = 8
904 self.context_use_ps1 = True
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000905 #
David Scherer7aced172000-08-15 01:13:23 +0000906 text = self.text
907 text.configure(wrap="char")
908 text.bind("<<newline-and-indent>>", self.enter_callback)
909 text.bind("<<plain-newline-and-indent>>", self.linefeed_callback)
910 text.bind("<<interrupt-execution>>", self.cancel_callback)
David Scherer7aced172000-08-15 01:13:23 +0000911 text.bind("<<end-of-file>>", self.eof_callback)
912 text.bind("<<open-stack-viewer>>", self.open_stack_viewer)
Kurt B. Kaiser57bfe5d2003-05-10 00:09:52 +0000913 text.bind("<<toggle-debugger>>", self.toggle_debugger)
David Scherer7aced172000-08-15 01:13:23 +0000914 text.bind("<<toggle-jit-stack-viewer>>", self.toggle_jit_stack_viewer)
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000915 if use_subprocess:
916 text.bind("<<view-restart>>", self.view_restart_mark)
917 text.bind("<<restart-shell>>", self.restart_shell)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000918 #
David Scherer7aced172000-08-15 01:13:23 +0000919 self.save_stdout = sys.stdout
920 self.save_stderr = sys.stderr
921 self.save_stdin = sys.stdin
Florent Xiclunad630c042010-04-02 07:24:52 +0000922 from idlelib import IOBinding
Serhiy Storchaka9abc8302013-01-25 15:30:35 +0200923 self.stdin = PseudoInputFile(self, "stdin", IOBinding.encoding)
924 self.stdout = PseudoOutputFile(self, "stdout", IOBinding.encoding)
925 self.stderr = PseudoOutputFile(self, "stderr", IOBinding.encoding)
926 self.console = PseudoOutputFile(self, "console", IOBinding.encoding)
Chui Tey5d2af632002-05-26 13:36:41 +0000927 if not use_subprocess:
928 sys.stdout = self.stdout
929 sys.stderr = self.stderr
Martin v. Löwise2b56242012-07-25 10:56:22 +0200930 sys.stdin = self.stdin
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000931 #
David Scherer7aced172000-08-15 01:13:23 +0000932 self.history = self.History(self.text)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000933 #
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000934 self.pollinterval = 50 # millisec
Chui Tey5d2af632002-05-26 13:36:41 +0000935
Kurt B. Kaiser4d5bc602004-06-06 01:29:22 +0000936 def get_standard_extension_names(self):
937 return idleConf.GetExtensions(shell_only=True)
938
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000939 reading = False
940 executing = False
941 canceled = False
942 endoffile = False
943 closing = False
Roger Serwyad8cad32013-04-03 00:42:24 -0500944 _stop_readline_flag = False
David Scherer7aced172000-08-15 01:13:23 +0000945
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +0000946 def set_warning_stream(self, stream):
Skip Montanarod9161422004-07-06 21:53:27 +0000947 global warning_stream
948 warning_stream = stream
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +0000949
950 def get_warning_stream(self):
951 return warning_stream
952
David Scherer7aced172000-08-15 01:13:23 +0000953 def toggle_debugger(self, event=None):
954 if self.executing:
955 tkMessageBox.showerror("Don't debug now",
956 "You can only toggle the debugger when idle",
957 master=self.text)
958 self.set_debugger_indicator()
959 return "break"
960 else:
961 db = self.interp.getdebugger()
962 if db:
963 self.close_debugger()
964 else:
965 self.open_debugger()
966
967 def set_debugger_indicator(self):
968 db = self.interp.getdebugger()
969 self.setvar("<<toggle-debugger>>", not not db)
970
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000971 def toggle_jit_stack_viewer(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +0000972 pass # All we need is the variable
973
974 def close_debugger(self):
975 db = self.interp.getdebugger()
976 if db:
977 self.interp.setdebugger(None)
978 db.close()
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000979 if self.interp.rpcclt:
980 RemoteDebugger.close_remote_debugger(self.interp.rpcclt)
David Scherer7aced172000-08-15 01:13:23 +0000981 self.resetoutput()
982 self.console.write("[DEBUG OFF]\n")
983 sys.ps1 = ">>> "
984 self.showprompt()
985 self.set_debugger_indicator()
986
987 def open_debugger(self):
Chui Tey5d2af632002-05-26 13:36:41 +0000988 if self.interp.rpcclt:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000989 dbg_gui = RemoteDebugger.start_remote_debugger(self.interp.rpcclt,
990 self)
991 else:
992 dbg_gui = Debugger.Debugger(self)
993 self.interp.setdebugger(dbg_gui)
994 dbg_gui.load_breakpoints()
Chui Tey5d2af632002-05-26 13:36:41 +0000995 sys.ps1 = "[DEBUG ON]\n>>> "
996 self.showprompt()
997 self.set_debugger_indicator()
998
David Scherer7aced172000-08-15 01:13:23 +0000999 def beginexecuting(self):
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +00001000 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +00001001 self.resetoutput()
1002 self.executing = 1
David Scherer7aced172000-08-15 01:13:23 +00001003
1004 def endexecuting(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +00001005 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +00001006 self.executing = 0
1007 self.canceled = 0
Chui Tey5d2af632002-05-26 13:36:41 +00001008 self.showprompt()
David Scherer7aced172000-08-15 01:13:23 +00001009
1010 def close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +00001011 "Extend EditorWindow.close()"
David Scherer7aced172000-08-15 01:13:23 +00001012 if self.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001013 response = tkMessageBox.askokcancel(
David Scherer7aced172000-08-15 01:13:23 +00001014 "Kill?",
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001015 "The program is still running!\n Do you want to kill it?",
David Scherer7aced172000-08-15 01:13:23 +00001016 default="ok",
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001017 parent=self.text)
Benjamin Peterson5b63acd2008-03-29 15:24:25 +00001018 if response is False:
David Scherer7aced172000-08-15 01:13:23 +00001019 return "cancel"
Roger Serwyad8cad32013-04-03 00:42:24 -05001020 self.stop_readline()
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001021 self.canceled = True
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +00001022 self.closing = True
Kurt B. Kaiser88957d82003-05-19 23:11:51 +00001023 return EditorWindow.close(self)
David Scherer7aced172000-08-15 01:13:23 +00001024
1025 def _close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +00001026 "Extend EditorWindow._close(), shut down debugger and execution server"
David Scherer7aced172000-08-15 01:13:23 +00001027 self.close_debugger()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001028 if use_subprocess:
1029 self.interp.kill_subprocess()
David Scherer7aced172000-08-15 01:13:23 +00001030 # Restore std streams
1031 sys.stdout = self.save_stdout
1032 sys.stderr = self.save_stderr
1033 sys.stdin = self.save_stdin
1034 # Break cycles
1035 self.interp = None
1036 self.console = None
David Scherer7aced172000-08-15 01:13:23 +00001037 self.flist.pyshell = None
1038 self.history = None
Kurt B. Kaiser83118c62002-06-24 17:03:37 +00001039 EditorWindow._close(self)
David Scherer7aced172000-08-15 01:13:23 +00001040
1041 def ispythonsource(self, filename):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +00001042 "Override EditorWindow method: never remove the colorizer"
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001043 return True
David Scherer7aced172000-08-15 01:13:23 +00001044
1045 def short_title(self):
1046 return self.shell_title
1047
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +00001048 COPYRIGHT = \
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001049 'Type "copyright", "credits" or "license()" for more information.'
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +00001050
David Scherer7aced172000-08-15 01:13:23 +00001051 def begin(self):
1052 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001053 if use_subprocess:
1054 nosub = ''
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001055 client = self.interp.start_subprocess()
1056 if not client:
1057 self.close()
Kurt B. Kaiser76637292004-01-21 22:10:01 +00001058 return False
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001059 else:
1060 nosub = "==== No Subprocess ===="
Raymond Hettingerbf3f69e2009-01-26 23:29:09 +00001061 self.write("Python %s on %s\n%s\n%s" %
1062 (sys.version, sys.platform, self.COPYRIGHT, nosub))
David Scherer7aced172000-08-15 01:13:23 +00001063 self.showprompt()
Georg Brandl6634bf22008-05-20 07:13:37 +00001064 import Tkinter
1065 Tkinter._default_root = None # 03Jan04 KBK What's this?
Kurt B. Kaiser76637292004-01-21 22:10:01 +00001066 return True
David Scherer7aced172000-08-15 01:13:23 +00001067
Roger Serwyad8cad32013-04-03 00:42:24 -05001068 def stop_readline(self):
1069 if not self.reading: # no nested mainloop to exit.
1070 return
1071 self._stop_readline_flag = True
1072 self.top.quit()
1073
David Scherer7aced172000-08-15 01:13:23 +00001074 def readline(self):
1075 save = self.reading
1076 try:
1077 self.reading = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001078 self.top.mainloop() # nested mainloop()
David Scherer7aced172000-08-15 01:13:23 +00001079 finally:
1080 self.reading = save
Roger Serwyad8cad32013-04-03 00:42:24 -05001081 if self._stop_readline_flag:
1082 self._stop_readline_flag = False
1083 return ""
David Scherer7aced172000-08-15 01:13:23 +00001084 line = self.text.get("iomark", "end-1c")
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001085 if len(line) == 0: # may be EOF if we quit our mainloop with Ctrl-C
1086 line = "\n"
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001087 if isinstance(line, unicode):
Florent Xiclunad630c042010-04-02 07:24:52 +00001088 from idlelib import IOBinding
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001089 try:
1090 line = line.encode(IOBinding.encoding)
1091 except UnicodeError:
1092 pass
David Scherer7aced172000-08-15 01:13:23 +00001093 self.resetoutput()
1094 if self.canceled:
1095 self.canceled = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001096 if not use_subprocess:
1097 raise KeyboardInterrupt
David Scherer7aced172000-08-15 01:13:23 +00001098 if self.endoffile:
1099 self.endoffile = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001100 line = ""
David Scherer7aced172000-08-15 01:13:23 +00001101 return line
1102
1103 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001104 return True
David Scherer7aced172000-08-15 01:13:23 +00001105
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001106 def cancel_callback(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +00001107 try:
1108 if self.text.compare("sel.first", "!=", "sel.last"):
1109 return # Active selection -- always use default binding
1110 except:
1111 pass
1112 if not (self.executing or self.reading):
1113 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001114 self.interp.write("KeyboardInterrupt\n")
David Scherer7aced172000-08-15 01:13:23 +00001115 self.showprompt()
1116 return "break"
1117 self.endoffile = 0
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001118 self.canceled = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001119 if (self.executing and self.interp.rpcclt):
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +00001120 if self.interp.getdebugger():
1121 self.interp.restart_subprocess()
1122 else:
1123 self.interp.interrupt_subprocess()
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001124 if self.reading:
1125 self.top.quit() # exit the nested mainloop() in readline()
David Scherer7aced172000-08-15 01:13:23 +00001126 return "break"
1127
1128 def eof_callback(self, event):
1129 if self.executing and not self.reading:
1130 return # Let the default binding (delete next char) take over
1131 if not (self.text.compare("iomark", "==", "insert") and
1132 self.text.compare("insert", "==", "end-1c")):
1133 return # Let the default binding (delete next char) take over
1134 if not self.executing:
David Scherer7aced172000-08-15 01:13:23 +00001135 self.resetoutput()
1136 self.close()
1137 else:
1138 self.canceled = 0
1139 self.endoffile = 1
1140 self.top.quit()
1141 return "break"
1142
David Scherer7aced172000-08-15 01:13:23 +00001143 def linefeed_callback(self, event):
1144 # Insert a linefeed without entering anything (still autoindented)
1145 if self.reading:
1146 self.text.insert("insert", "\n")
1147 self.text.see("insert")
1148 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001149 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001150 return "break"
1151
1152 def enter_callback(self, event):
1153 if self.executing and not self.reading:
1154 return # Let the default binding (insert '\n') take over
1155 # If some text is selected, recall the selection
1156 # (but only if this before the I/O mark)
1157 try:
1158 sel = self.text.get("sel.first", "sel.last")
1159 if sel:
1160 if self.text.compare("sel.last", "<=", "iomark"):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001161 self.recall(sel, event)
David Scherer7aced172000-08-15 01:13:23 +00001162 return "break"
1163 except:
1164 pass
1165 # If we're strictly before the line containing iomark, recall
1166 # the current line, less a leading prompt, less leading or
1167 # trailing whitespace
1168 if self.text.compare("insert", "<", "iomark linestart"):
1169 # Check if there's a relevant stdin range -- if so, use it
1170 prev = self.text.tag_prevrange("stdin", "insert")
1171 if prev and self.text.compare("insert", "<", prev[1]):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001172 self.recall(self.text.get(prev[0], prev[1]), event)
David Scherer7aced172000-08-15 01:13:23 +00001173 return "break"
1174 next = self.text.tag_nextrange("stdin", "insert")
1175 if next and self.text.compare("insert lineend", ">=", next[0]):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001176 self.recall(self.text.get(next[0], next[1]), event)
David Scherer7aced172000-08-15 01:13:23 +00001177 return "break"
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001178 # No stdin mark -- just get the current line, less any prompt
Kurt B. Kaiserb1754452005-11-18 22:05:48 +00001179 indices = self.text.tag_nextrange("console", "insert linestart")
1180 if indices and \
1181 self.text.compare(indices[0], "<=", "insert linestart"):
1182 self.recall(self.text.get(indices[1], "insert lineend"), event)
1183 else:
1184 self.recall(self.text.get("insert linestart", "insert lineend"), event)
David Scherer7aced172000-08-15 01:13:23 +00001185 return "break"
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001186 # If we're between the beginning of the line and the iomark, i.e.
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001187 # in the prompt area, move to the end of the prompt
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001188 if self.text.compare("insert", "<", "iomark"):
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001189 self.text.mark_set("insert", "iomark")
David Scherer7aced172000-08-15 01:13:23 +00001190 # If we're in the current input and there's only whitespace
1191 # beyond the cursor, erase that whitespace first
1192 s = self.text.get("insert", "end-1c")
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001193 if s and not s.strip():
David Scherer7aced172000-08-15 01:13:23 +00001194 self.text.delete("insert", "end-1c")
1195 # If we're in the current input before its last line,
1196 # insert a newline right at the insert point
1197 if self.text.compare("insert", "<", "end-1c linestart"):
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001198 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001199 return "break"
1200 # We're in the last line; append a newline and submit it
1201 self.text.mark_set("insert", "end-1c")
1202 if self.reading:
1203 self.text.insert("insert", "\n")
1204 self.text.see("insert")
1205 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001206 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001207 self.text.tag_add("stdin", "iomark", "end-1c")
1208 self.text.update_idletasks()
1209 if self.reading:
1210 self.top.quit() # Break out of recursive mainloop() in raw_input()
1211 else:
1212 self.runit()
1213 return "break"
1214
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001215 def recall(self, s, event):
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001216 # remove leading and trailing empty or whitespace lines
1217 s = re.sub(r'^\s*\n', '' , s)
1218 s = re.sub(r'\n\s*$', '', s)
1219 lines = s.split('\n')
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001220 self.text.undo_block_start()
1221 try:
1222 self.text.tag_remove("sel", "1.0", "end")
1223 self.text.mark_set("insert", "end-1c")
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001224 prefix = self.text.get("insert linestart", "insert")
1225 if prefix.rstrip().endswith(':'):
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001226 self.newline_and_indent_event(event)
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001227 prefix = self.text.get("insert linestart", "insert")
1228 self.text.insert("insert", lines[0].strip())
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001229 if len(lines) > 1:
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001230 orig_base_indent = re.search(r'^([ \t]*)', lines[0]).group(0)
1231 new_base_indent = re.search(r'^([ \t]*)', prefix).group(0)
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001232 for line in lines[1:]:
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001233 if line.startswith(orig_base_indent):
1234 # replace orig base indentation with new indentation
1235 line = new_base_indent + line[len(orig_base_indent):]
1236 self.text.insert('insert', '\n'+line.rstrip())
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001237 finally:
1238 self.text.see("insert")
1239 self.text.undo_block_stop()
David Scherer7aced172000-08-15 01:13:23 +00001240
1241 def runit(self):
1242 line = self.text.get("iomark", "end-1c")
1243 # Strip off last newline and surrounding whitespace.
1244 # (To allow you to hit return twice to end a statement.)
1245 i = len(line)
1246 while i > 0 and line[i-1] in " \t":
1247 i = i-1
1248 if i > 0 and line[i-1] == "\n":
1249 i = i-1
1250 while i > 0 and line[i-1] in " \t":
1251 i = i-1
1252 line = line[:i]
1253 more = self.interp.runsource(line)
David Scherer7aced172000-08-15 01:13:23 +00001254
David Scherer7aced172000-08-15 01:13:23 +00001255 def open_stack_viewer(self, event=None):
Chui Tey5d2af632002-05-26 13:36:41 +00001256 if self.interp.rpcclt:
1257 return self.interp.remote_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +00001258 try:
1259 sys.last_traceback
1260 except:
1261 tkMessageBox.showerror("No stack trace",
1262 "There is no stack trace yet.\n"
1263 "(sys.last_traceback is not defined)",
1264 master=self.text)
1265 return
Florent Xiclunad630c042010-04-02 07:24:52 +00001266 from idlelib.StackViewer import StackBrowser
David Scherer7aced172000-08-15 01:13:23 +00001267 sv = StackBrowser(self.root, self.flist)
1268
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001269 def view_restart_mark(self, event=None):
1270 self.text.see("iomark")
1271 self.text.see("restart")
1272
1273 def restart_shell(self, event=None):
Terry Jan Reedyb98000a2012-01-31 02:09:25 -05001274 "Callback for Run/Restart Shell Cntl-F6"
1275 self.interp.restart_subprocess(with_cwd=True)
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001276
David Scherer7aced172000-08-15 01:13:23 +00001277 def showprompt(self):
1278 self.resetoutput()
1279 try:
1280 s = str(sys.ps1)
1281 except:
1282 s = ""
1283 self.console.write(s)
1284 self.text.mark_set("insert", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001285 self.set_line_and_column()
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +00001286 self.io.reset_undo()
David Scherer7aced172000-08-15 01:13:23 +00001287
1288 def resetoutput(self):
1289 source = self.text.get("iomark", "end-1c")
1290 if self.history:
Terry Jan Reedyb638a382013-08-13 19:51:04 -04001291 self.history.store(source)
David Scherer7aced172000-08-15 01:13:23 +00001292 if self.text.get("end-2c") != "\n":
1293 self.text.insert("end-1c", "\n")
1294 self.text.mark_set("iomark", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001295 self.set_line_and_column()
David Scherer7aced172000-08-15 01:13:23 +00001296 sys.stdout.softspace = 0
1297
1298 def write(self, s, tags=()):
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001299 try:
1300 self.text.mark_gravity("iomark", "right")
1301 OutputWindow.write(self, s, tags, "iomark")
1302 self.text.mark_gravity("iomark", "left")
1303 except:
1304 pass
David Scherer7aced172000-08-15 01:13:23 +00001305 if self.canceled:
1306 self.canceled = 0
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001307 if not use_subprocess:
1308 raise KeyboardInterrupt
David Scherer7aced172000-08-15 01:13:23 +00001309
Andrew Svetlov5018db72012-11-01 22:39:14 +02001310 def rmenu_check_cut(self):
1311 try:
1312 if self.text.compare('sel.first', '<', 'iomark'):
1313 return 'disabled'
1314 except TclError: # no selection, so the index 'sel.first' doesn't exist
1315 return 'disabled'
1316 return super(PyShell, self).rmenu_check_cut()
1317
1318 def rmenu_check_paste(self):
1319 if self.text.compare('insert', '<', 'iomark'):
1320 return 'disabled'
1321 return super(PyShell, self).rmenu_check_paste()
1322
Serhiy Storchaka9abc8302013-01-25 15:30:35 +02001323class PseudoFile(io.TextIOBase):
David Scherer7aced172000-08-15 01:13:23 +00001324
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001325 def __init__(self, shell, tags, encoding=None):
David Scherer7aced172000-08-15 01:13:23 +00001326 self.shell = shell
1327 self.tags = tags
Chui Tey5d2af632002-05-26 13:36:41 +00001328 self.softspace = 0
Serhiy Storchaka9abc8302013-01-25 15:30:35 +02001329 self._encoding = encoding
David Scherer7aced172000-08-15 01:13:23 +00001330
Serhiy Storchaka9abc8302013-01-25 15:30:35 +02001331 @property
1332 def encoding(self):
1333 return self._encoding
David Scherer7aced172000-08-15 01:13:23 +00001334
Serhiy Storchaka9abc8302013-01-25 15:30:35 +02001335 @property
1336 def name(self):
1337 return '<%s>' % self.tags
David Scherer7aced172000-08-15 01:13:23 +00001338
1339 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001340 return True
David Scherer7aced172000-08-15 01:13:23 +00001341
Serhiy Storchaka9abc8302013-01-25 15:30:35 +02001342
1343class PseudoOutputFile(PseudoFile):
1344
1345 def writable(self):
1346 return True
Martin v. Löwise2b56242012-07-25 10:56:22 +02001347
1348 def write(self, s):
Serhiy Storchaka9abc8302013-01-25 15:30:35 +02001349 if self.closed:
1350 raise ValueError("write to closed file")
Serhiy Storchaka7057f3f2013-12-10 10:04:41 +02001351 if type(s) not in (unicode, str, bytearray):
1352 # See issue #19481
1353 if isinstance(s, unicode):
1354 s = unicode.__getslice__(s, None, None)
1355 elif isinstance(s, str):
1356 s = str.__str__(s)
1357 elif isinstance(s, bytearray):
1358 s = bytearray.__str__(s)
1359 else:
1360 raise TypeError('must be string, not ' + type(s).__name__)
Serhiy Storchaka9abc8302013-01-25 15:30:35 +02001361 return self.shell.write(s, self.tags)
1362
1363
1364class PseudoInputFile(PseudoFile):
1365
1366 def __init__(self, shell, tags, encoding=None):
1367 PseudoFile.__init__(self, shell, tags, encoding)
1368 self._line_buffer = ''
1369
1370 def readable(self):
1371 return True
1372
1373 def read(self, size=-1):
1374 if self.closed:
1375 raise ValueError("read from closed file")
1376 if size is None:
1377 size = -1
1378 elif not isinstance(size, int):
1379 raise TypeError('must be int, not ' + type(size).__name__)
1380 result = self._line_buffer
1381 self._line_buffer = ''
1382 if size < 0:
1383 while True:
1384 line = self.shell.readline()
1385 if not line: break
1386 result += line
1387 else:
1388 while len(result) < size:
1389 line = self.shell.readline()
1390 if not line: break
1391 result += line
1392 self._line_buffer = result[size:]
1393 result = result[:size]
1394 return result
1395
1396 def readline(self, size=-1):
1397 if self.closed:
1398 raise ValueError("read from closed file")
1399 if size is None:
1400 size = -1
1401 elif not isinstance(size, int):
1402 raise TypeError('must be int, not ' + type(size).__name__)
1403 line = self._line_buffer or self.shell.readline()
1404 if size < 0:
1405 size = len(line)
Serhiy Storchaka0b6b3352013-12-25 14:24:17 +02001406 eol = line.find('\n', 0, size)
1407 if eol >= 0:
1408 size = eol + 1
Serhiy Storchaka9abc8302013-01-25 15:30:35 +02001409 self._line_buffer = line[size:]
1410 return line[:size]
Martin v. Löwise2b56242012-07-25 10:56:22 +02001411
Roger Serwy53dc4f02013-04-11 19:13:21 -05001412 def close(self):
1413 self.shell.close()
1414
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001415
David Scherer7aced172000-08-15 01:13:23 +00001416usage_msg = """\
David Scherer7aced172000-08-15 01:13:23 +00001417
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001418USAGE: idle [-deins] [-t title] [file]*
1419 idle [-dns] [-t title] (-c cmd | -r file) [arg]*
1420 idle [-dns] [-t title] - [arg]*
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001421
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001422 -h print this help message and exit
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001423 -n run IDLE without a subprocess (see Help/IDLE Help for details)
David Scherer7aced172000-08-15 01:13:23 +00001424
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001425The following options will override the IDLE 'settings' configuration:
Kurt B. Kaiser96d88422001-07-17 04:59:01 +00001426
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001427 -e open an edit window
1428 -i open a shell window
1429
1430The following options imply -i and will open a shell:
1431
1432 -c cmd run the command in a shell, or
1433 -r file run script from file
1434
1435 -d enable the debugger
1436 -s run $IDLESTARTUP or $PYTHONSTARTUP before anything else
1437 -t title set title of shell window
1438
1439A default edit window will be bypassed when -c, -r, or - are used.
1440
1441[arg]* are passed to the command (-c) or script (-r) in sys.argv[1:].
1442
1443Examples:
1444
1445idle
1446 Open an edit window or shell depending on IDLE's configuration.
1447
1448idle foo.py foobar.py
1449 Edit the files, also open a shell if configured to start with shell.
1450
1451idle -est "Baz" foo.py
1452 Run $IDLESTARTUP or $PYTHONSTARTUP, edit foo.py, and open a shell
1453 window with the title "Baz".
1454
1455idle -c "import sys; print sys.argv" "foo"
1456 Open a shell window and run the command, passing "-c" in sys.argv[0]
1457 and "foo" in sys.argv[1].
1458
1459idle -d -s -r foo.py "Hello World"
1460 Open a shell window, run a startup script, enable the debugger, and
1461 run foo.py, passing "foo.py" in sys.argv[0] and "Hello World" in
1462 sys.argv[1].
1463
1464echo "import sys; print sys.argv" | idle - "foobar"
1465 Open a shell window, run the script piped in, passing '' in sys.argv[0]
1466 and "foobar" in sys.argv[1].
David Scherer7aced172000-08-15 01:13:23 +00001467"""
1468
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001469def main():
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001470 global flist, root, use_subprocess
David Scherer7aced172000-08-15 01:13:23 +00001471
Terry Jan Reedy8eab0082013-06-28 23:51:34 -04001472 capture_warnings(True)
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001473 use_subprocess = True
Roger Serwy34d0c662013-03-31 23:28:55 -05001474 enable_shell = False
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001475 enable_edit = False
1476 debug = False
1477 cmd = None
1478 script = None
1479 startup = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001480 try:
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001481 opts, args = getopt.getopt(sys.argv[1:], "c:deihnr:st:")
Terry Jan Reedy2b149862013-06-29 00:59:34 -04001482 except getopt.error as msg:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001483 sys.stderr.write("Error: %s\n" % str(msg))
1484 sys.stderr.write(usage_msg)
1485 sys.exit(2)
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001486 for o, a in opts:
1487 if o == '-c':
1488 cmd = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001489 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001490 if o == '-d':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001491 debug = True
1492 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001493 if o == '-e':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001494 enable_edit = True
1495 if o == '-h':
1496 sys.stdout.write(usage_msg)
1497 sys.exit()
1498 if o == '-i':
1499 enable_shell = True
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001500 if o == '-n':
1501 use_subprocess = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001502 if o == '-r':
1503 script = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001504 if os.path.isfile(script):
1505 pass
1506 else:
1507 print "No script file: ", script
1508 sys.exit()
1509 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001510 if o == '-s':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001511 startup = True
1512 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001513 if o == '-t':
1514 PyShell.shell_title = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001515 enable_shell = True
1516 if args and args[0] == '-':
1517 cmd = sys.stdin.read()
1518 enable_shell = True
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001519 # process sys.argv and sys.path:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001520 for i in range(len(sys.path)):
1521 sys.path[i] = os.path.abspath(sys.path[i])
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001522 if args and args[0] == '-':
1523 sys.argv = [''] + args[1:]
1524 elif cmd:
1525 sys.argv = ['-c'] + args
1526 elif script:
1527 sys.argv = [script] + args
1528 elif args:
1529 enable_edit = True
1530 pathx = []
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001531 for filename in args:
1532 pathx.append(os.path.dirname(filename))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001533 for dir in pathx:
1534 dir = os.path.abspath(dir)
Florent Xiclunad630c042010-04-02 07:24:52 +00001535 if dir not in sys.path:
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001536 sys.path.insert(0, dir)
Kurt B. Kaiserff002b92002-12-21 21:39:11 +00001537 else:
1538 dir = os.getcwd()
1539 if not dir in sys.path:
1540 sys.path.insert(0, dir)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001541 # check the IDLE settings configuration (but command line overrides)
1542 edit_start = idleConf.GetOption('main', 'General',
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001543 'editor-on-startup', type='bool')
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001544 enable_edit = enable_edit or edit_start
Roger Serwy34d0c662013-03-31 23:28:55 -05001545 enable_shell = enable_shell or not enable_edit
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001546 # start editor and/or shell windows:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001547 root = Tk(className="Idle")
Ronald Oussoren19302d92006-06-11 14:33:36 +00001548
Terry Jan Reedy4ade2d22014-02-08 09:39:51 -05001549 # set application icon
1550 icondir = os.path.join(os.path.dirname(__file__), 'Icons')
1551 if system() == 'Windows':
1552 iconfile = os.path.join(icondir, 'idle.ico')
1553 root.wm_iconbitmap(default=iconfile)
1554 elif TkVersion >= 8.5:
1555 ext = '.png' if TkVersion >= 8.6 else '.gif'
1556 iconfiles = [os.path.join(icondir, 'idle_%d%s' % (size, ext))
1557 for size in (16, 32, 48)]
1558 icons = [PhotoImage(file=iconfile) for iconfile in iconfiles]
1559 root.tk.call('wm', 'iconphoto', str(root), "-default", *icons)
1560
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001561 fixwordbreaks(root)
1562 root.withdraw()
1563 flist = PyShellFileList(root)
Ronald Oussoren19302d92006-06-11 14:33:36 +00001564 macosxSupport.setupApp(root, flist)
1565
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001566 if enable_edit:
1567 if not (cmd or script):
Andrew Svetlov7c010ee2012-03-21 13:35:08 +02001568 for filename in args[:]:
1569 if flist.open(filename) is None:
1570 # filename is a directory actually, disconsider it
1571 args.remove(filename)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001572 if not args:
1573 flist.new()
Ned Deily278543d2013-12-10 16:21:58 -08001574
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001575 if enable_shell:
Ronald Oussoren19302d92006-06-11 14:33:36 +00001576 shell = flist.open_shell()
1577 if not shell:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001578 return # couldn't open shell
Ned Deily57847df2014-03-27 20:47:04 -07001579 if macosxSupport.isAquaTk() and flist.dict:
Ronald Oussoren19302d92006-06-11 14:33:36 +00001580 # On OSX: when the user has double-clicked on a file that causes
Tim Peters4f96f1f2006-06-11 19:42:51 +00001581 # IDLE to be launched the shell window will open just in front of
1582 # the file she wants to see. Lower the interpreter window when
Ronald Oussoren19302d92006-06-11 14:33:36 +00001583 # there are open files.
1584 shell.top.lower()
Ned Deily278543d2013-12-10 16:21:58 -08001585 else:
1586 shell = flist.pyshell
Ronald Oussoren19302d92006-06-11 14:33:36 +00001587
Ned Deily278543d2013-12-10 16:21:58 -08001588 # Handle remaining options. If any of these are set, enable_shell
1589 # was set also, so shell must be true to reach here.
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001590 if debug:
1591 shell.open_debugger()
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001592 if startup:
1593 filename = os.environ.get("IDLESTARTUP") or \
1594 os.environ.get("PYTHONSTARTUP")
1595 if filename and os.path.isfile(filename):
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001596 shell.interp.execfile(filename)
Ned Deily278543d2013-12-10 16:21:58 -08001597 if cmd or script:
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001598 shell.interp.runcommand("""if 1:
1599 import sys as _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001600 _sys.argv = %r
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001601 del _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001602 \n""" % (sys.argv,))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001603 if cmd:
1604 shell.interp.execsource(cmd)
1605 elif script:
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001606 shell.interp.prepend_syspath(script)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001607 shell.interp.execfile(script)
Ned Deily278543d2013-12-10 16:21:58 -08001608 elif shell:
1609 # If there is a shell window and no cmd or script in progress,
1610 # check for problematic OS X Tk versions and print a warning
1611 # message in the IDLE shell window; this is less intrusive
1612 # than always opening a separate window.
1613 tkversionwarning = macosxSupport.tkVersionWarning(root)
1614 if tkversionwarning:
1615 shell.interp.runcommand("print('%s')" % tkversionwarning)
Ned Deily2a6f4b32011-01-30 00:18:47 +00001616
Terry Jan Reedyeaa7e782012-05-26 20:33:32 -04001617 while flist.inversedict: # keep IDLE running while files are open.
1618 root.mainloop()
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001619 root.destroy()
Terry Jan Reedy8eab0082013-06-28 23:51:34 -04001620 capture_warnings(False)
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001621
David Scherer7aced172000-08-15 01:13:23 +00001622if __name__ == "__main__":
Kurt B. Kaiser9e8b8282003-06-15 17:38:45 +00001623 sys.modules['PyShell'] = sys.modules['__main__']
David Scherer7aced172000-08-15 01:13:23 +00001624 main()
Terry Jan Reedy8eab0082013-06-28 23:51:34 -04001625
1626capture_warnings(False) # Make sure turned off; see issue 18081