blob: 79db883e81884bf2473ba21122c83cd6abab55ca [file] [log] [blame]
David Scherer7aced172000-08-15 01:13:23 +00001#! /usr/bin/env python
Terry Jan Reedybee003c2014-09-19 22:37:24 -04002from __future__ import print_function
David Scherer7aced172000-08-15 01:13:23 +00003
David Scherer7aced172000-08-15 01:13:23 +00004import os
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +00005import os.path
David Scherer7aced172000-08-15 01:13:23 +00006import sys
7import string
8import getopt
9import re
Chui Tey5d2af632002-05-26 13:36:41 +000010import socket
11import time
Kurt B. Kaiser003091c2003-02-17 18:57:16 +000012import threading
Chui Tey5d2af632002-05-26 13:36:41 +000013import traceback
Kurt B. Kaiser62833982002-09-18 17:07:05 +000014import types
Martin v. Löwise2b56242012-07-25 10:56:22 +020015import io
David Scherer7aced172000-08-15 01:13:23 +000016
17import linecache
18from code import InteractiveInterpreter
Terry Jan Reedy4ade2d22014-02-08 09:39:51 -050019from platform import python_version, system
David Scherer7aced172000-08-15 01:13:23 +000020
Kurt B. Kaiser2303b1c2003-11-24 05:26:16 +000021try:
Georg Brandl6634bf22008-05-20 07:13:37 +000022 from Tkinter import *
Kurt B. Kaiser2303b1c2003-11-24 05:26:16 +000023except ImportError:
Terry Jan Reedybee003c2014-09-19 22:37:24 -040024 print("** IDLE can't import Tkinter.\n"
25 "Your Python may not be configured for Tk. **", file=sys.__stderr__)
Kurt B. Kaiser2303b1c2003-11-24 05:26:16 +000026 sys.exit(1)
Georg Brandl6634bf22008-05-20 07:13:37 +000027import tkMessageBox
David Scherer7aced172000-08-15 01:13:23 +000028
Florent Xiclunad630c042010-04-02 07:24:52 +000029from idlelib.EditorWindow import EditorWindow, fixwordbreaks
30from idlelib.FileList import FileList
31from idlelib.ColorDelegator import ColorDelegator
32from idlelib.UndoDelegator import UndoDelegator
33from idlelib.OutputWindow import OutputWindow
34from idlelib.configHandler import idleConf
35from idlelib import idlever
36from idlelib import rpc
37from idlelib import Debugger
38from idlelib import RemoteDebugger
39from idlelib import macosxSupport
Chui Tey5d2af632002-05-26 13:36:41 +000040
Kurt B. Kaiserb9764192002-09-23 04:10:37 +000041IDENTCHARS = string.ascii_letters + string.digits + "_"
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +000042HOST = '127.0.0.1' # python execution server on localhost loopback
43PORT = 0 # someday pass in host, port for remote debug capability
Kurt B. Kaiserb9764192002-09-23 04:10:37 +000044
Kurt B. Kaisera00050f2003-05-08 20:26:55 +000045try:
46 from signal import SIGTERM
47except ImportError:
48 SIGTERM = 15
49
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000050# Override warnings module to write to warning_stream. Initialize to send IDLE
51# internal warnings to the console. ScriptBinding.check_syntax() will
52# temporarily redirect the stream to the shell window to display warnings when
53# checking user's code.
Terry Jan Reedy8eab0082013-06-28 23:51:34 -040054warning_stream = sys.__stderr__ # None, at least on Windows, if no console.
55import warnings
56
57def idle_formatwarning(message, category, filename, lineno, line=None):
58 """Format warnings the IDLE way."""
59
60 s = "\nWarning (from warnings module):\n"
61 s += ' File \"%s\", line %s\n' % (filename, lineno)
62 if line is None:
63 line = linecache.getline(filename, lineno)
64 line = line.strip()
65 if line:
66 s += " %s\n" % line
67 s += "%s: %s\n" % (category.__name__, message)
68 return s
69
70def idle_showwarning(
71 message, category, filename, lineno, file=None, line=None):
72 """Show Idle-format warning (after replacing warnings.showwarning).
73
74 The differences are the formatter called, the file=None replacement,
75 which can be None, the capture of the consequence AttributeError,
76 and the output of a hard-coded prompt.
77 """
78 if file is None:
79 file = warning_stream
80 try:
81 file.write(idle_formatwarning(
82 message, category, filename, lineno, line=line))
83 file.write(">>> ")
84 except (AttributeError, IOError):
85 pass # if file (probably __stderr__) is invalid, skip warning.
86
87_warnings_showwarning = None
88
89def capture_warnings(capture):
90 "Replace warning.showwarning with idle_showwarning, or reverse."
91
92 global _warnings_showwarning
93 if capture:
94 if _warnings_showwarning is None:
95 _warnings_showwarning = warnings.showwarning
96 warnings.showwarning = idle_showwarning
97 else:
98 if _warnings_showwarning is not None:
99 warnings.showwarning = _warnings_showwarning
100 _warnings_showwarning = None
101
102capture_warnings(True)
Chui Tey5d2af632002-05-26 13:36:41 +0000103
Kurt B. Kaiserf7a88992004-11-13 21:05:58 +0000104def extended_linecache_checkcache(filename=None,
105 orig_checkcache=linecache.checkcache):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000106 """Extend linecache.checkcache to preserve the <pyshell#...> entries
107
Kurt B. Kaiserf7a88992004-11-13 21:05:58 +0000108 Rather than repeating the linecache code, patch it to save the
109 <pyshell#...> entries, call the original linecache.checkcache()
Guilherme Polof198ac22009-08-14 14:03:07 +0000110 (skipping them), and then restore the saved entries.
Kurt B. Kaiserf7a88992004-11-13 21:05:58 +0000111
112 orig_checkcache is bound at definition time to the original
113 method, allowing it to be patched.
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000114 """
David Scherer7aced172000-08-15 01:13:23 +0000115 cache = linecache.cache
116 save = {}
Guilherme Polof198ac22009-08-14 14:03:07 +0000117 for key in list(cache):
118 if key[:1] + key[-1:] == '<>':
119 save[key] = cache.pop(key)
120 orig_checkcache(filename)
David Scherer7aced172000-08-15 01:13:23 +0000121 cache.update(save)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000122
Kurt B. Kaiser81885592002-11-29 22:10:53 +0000123# Patch linecache.checkcache():
124linecache.checkcache = extended_linecache_checkcache
David Scherer7aced172000-08-15 01:13:23 +0000125
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000126
David Scherer7aced172000-08-15 01:13:23 +0000127class PyShellEditorWindow(EditorWindow):
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000128 "Regular text edit window in IDLE, supports breakpoints"
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000129
David Scherer7aced172000-08-15 01:13:23 +0000130 def __init__(self, *args):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000131 self.breakpoints = []
Raymond Hettinger931237e2003-07-09 18:48:24 +0000132 EditorWindow.__init__(self, *args)
David Scherer7aced172000-08-15 01:13:23 +0000133 self.text.bind("<<set-breakpoint-here>>", self.set_breakpoint_here)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000134 self.text.bind("<<clear-breakpoint-here>>", self.clear_breakpoint_here)
David Scherer7aced172000-08-15 01:13:23 +0000135 self.text.bind("<<open-python-shell>>", self.flist.open_shell)
136
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000137 self.breakpointPath = os.path.join(idleConf.GetUserCfgDir(),
138 'breakpoints.lst')
Chui Teya2adb0f2002-11-04 22:14:54 +0000139 # whenever a file is changed, restore breakpoints
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000140 def filename_changed_hook(old_hook=self.io.filename_change_hook,
141 self=self):
Chui Teya2adb0f2002-11-04 22:14:54 +0000142 self.restore_file_breaks()
143 old_hook()
144 self.io.set_filename_change_hook(filename_changed_hook)
Roger Serwyd7c9d9c2013-04-02 22:37:12 -0500145 if self.io.filename:
146 self.restore_file_breaks()
Terry Jan Reedy25327d42014-08-08 23:33:11 -0400147 self.color_breakpoint_text()
Chui Teya2adb0f2002-11-04 22:14:54 +0000148
Andrew Svetlov5018db72012-11-01 22:39:14 +0200149 rmenu_specs = [
150 ("Cut", "<<cut>>", "rmenu_check_cut"),
151 ("Copy", "<<copy>>", "rmenu_check_copy"),
152 ("Paste", "<<paste>>", "rmenu_check_paste"),
153 ("Set Breakpoint", "<<set-breakpoint-here>>", None),
154 ("Clear Breakpoint", "<<clear-breakpoint-here>>", None)
155 ]
David Scherer7aced172000-08-15 01:13:23 +0000156
Terry Jan Reedy25327d42014-08-08 23:33:11 -0400157 def color_breakpoint_text(self, color=True):
158 "Turn colorizing of breakpoint text on or off"
Terry Jan Reedy08da46e2014-10-12 22:58:42 -0400159 if self.io is None:
160 # possible due to update in restore_file_breaks
161 return
Terry Jan Reedy25327d42014-08-08 23:33:11 -0400162 if color:
163 theme = idleConf.GetOption('main','Theme','name')
164 cfg = idleConf.GetHighlight(theme, "break")
165 else:
166 cfg = {'foreground': '', 'background': ''}
167 self.text.tag_config('BREAK', cfg)
168
Chui Teya2adb0f2002-11-04 22:14:54 +0000169 def set_breakpoint(self, lineno):
170 text = self.text
171 filename = self.io.filename
172 text.tag_add("BREAK", "%d.0" % lineno, "%d.0" % (lineno+1))
173 try:
174 i = self.breakpoints.index(lineno)
175 except ValueError: # only add if missing, i.e. do once
176 self.breakpoints.append(lineno)
177 try: # update the subprocess debugger
178 debug = self.flist.pyshell.interp.debugger
179 debug.set_breakpoint_here(filename, lineno)
180 except: # but debugger may not be active right now....
181 pass
182
David Scherer7aced172000-08-15 01:13:23 +0000183 def set_breakpoint_here(self, event=None):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000184 text = self.text
185 filename = self.io.filename
186 if not filename:
187 text.bell()
David Scherer7aced172000-08-15 01:13:23 +0000188 return
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000189 lineno = int(float(text.index("insert")))
Chui Teya2adb0f2002-11-04 22:14:54 +0000190 self.set_breakpoint(lineno)
David Scherer7aced172000-08-15 01:13:23 +0000191
Kurt B. Kaiser669f4c32002-06-20 04:01:47 +0000192 def clear_breakpoint_here(self, event=None):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000193 text = self.text
194 filename = self.io.filename
195 if not filename:
196 text.bell()
Kurt B. Kaiser669f4c32002-06-20 04:01:47 +0000197 return
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000198 lineno = int(float(text.index("insert")))
199 try:
200 self.breakpoints.remove(lineno)
201 except:
202 pass
203 text.tag_remove("BREAK", "insert linestart",\
204 "insert lineend +1char")
205 try:
206 debug = self.flist.pyshell.interp.debugger
207 debug.clear_breakpoint_here(filename, lineno)
208 except:
209 pass
210
211 def clear_file_breaks(self):
212 if self.breakpoints:
213 text = self.text
214 filename = self.io.filename
215 if not filename:
216 text.bell()
217 return
218 self.breakpoints = []
219 text.tag_remove("BREAK", "1.0", END)
220 try:
221 debug = self.flist.pyshell.interp.debugger
222 debug.clear_file_breaks(filename)
223 except:
224 pass
225
Chui Teya2adb0f2002-11-04 22:14:54 +0000226 def store_file_breaks(self):
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000227 "Save breakpoints when file is saved"
228 # XXX 13 Dec 2002 KBK Currently the file must be saved before it can
229 # be run. The breaks are saved at that time. If we introduce
230 # a temporary file save feature the save breaks functionality
231 # needs to be re-verified, since the breaks at the time the
232 # temp file is created may differ from the breaks at the last
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000233 # permanent save of the file. Currently, a break introduced
234 # after a save will be effective, but not persistent.
235 # This is necessary to keep the saved breaks synched with the
236 # saved file.
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000237 #
Terry Jan Reedy987a02b2014-10-12 01:10:58 -0400238 # Breakpoints are set as tagged ranges in the text.
239 # Since a modified file has to be saved before it is
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000240 # run, and since self.breakpoints (from which the subprocess
241 # debugger is loaded) is updated during the save, the visible
242 # breaks stay synched with the subprocess even if one of these
243 # unexpected breakpoint deletions occurs.
244 breaks = self.breakpoints
245 filename = self.io.filename
Chui Teya2adb0f2002-11-04 22:14:54 +0000246 try:
Ned Deily40ad0412011-12-14 14:57:43 -0800247 with open(self.breakpointPath,"r") as old_file:
248 lines = old_file.readlines()
Chui Teya2adb0f2002-11-04 22:14:54 +0000249 except IOError:
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000250 lines = []
Ned Deily40ad0412011-12-14 14:57:43 -0800251 try:
252 with open(self.breakpointPath,"w") as new_file:
253 for line in lines:
254 if not line.startswith(filename + '='):
255 new_file.write(line)
256 self.update_breakpoints()
257 breaks = self.breakpoints
258 if breaks:
259 new_file.write(filename + '=' + str(breaks) + '\n')
260 except IOError as err:
261 if not getattr(self.root, "breakpoint_error_displayed", False):
262 self.root.breakpoint_error_displayed = True
263 tkMessageBox.showerror(title='IDLE Error',
264 message='Unable to update breakpoint list:\n%s'
265 % str(err),
266 parent=self.text)
Chui Teya2adb0f2002-11-04 22:14:54 +0000267
268 def restore_file_breaks(self):
269 self.text.update() # this enables setting "BREAK" tags to be visible
Roger Serwyd7c9d9c2013-04-02 22:37:12 -0500270 if self.io is None:
271 # can happen if IDLE closes due to the .update() call
272 return
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000273 filename = self.io.filename
274 if filename is None:
275 return
Chui Tey69371d62002-11-04 23:39:45 +0000276 if os.path.isfile(self.breakpointPath):
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000277 lines = open(self.breakpointPath,"r").readlines()
Chui Tey69371d62002-11-04 23:39:45 +0000278 for line in lines:
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000279 if line.startswith(filename + '='):
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000280 breakpoint_linenumbers = eval(line[len(filename)+1:])
Chui Tey69371d62002-11-04 23:39:45 +0000281 for breakpoint_linenumber in breakpoint_linenumbers:
282 self.set_breakpoint(breakpoint_linenumber)
Chui Teya2adb0f2002-11-04 22:14:54 +0000283
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000284 def update_breakpoints(self):
285 "Retrieves all the breakpoints in the current window"
Chui Teya2adb0f2002-11-04 22:14:54 +0000286 text = self.text
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000287 ranges = text.tag_ranges("BREAK")
288 linenumber_list = self.ranges_to_linenumbers(ranges)
289 self.breakpoints = linenumber_list
290
291 def ranges_to_linenumbers(self, ranges):
292 lines = []
293 for index in range(0, len(ranges), 2):
Andrew Svetlov8a15c372012-07-31 19:51:27 +0300294 lineno = int(float(ranges[index].string))
295 end = int(float(ranges[index+1].string))
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000296 while lineno < end:
297 lines.append(lineno)
298 lineno += 1
299 return lines
300
Kurt B. Kaiser11220fa2002-12-24 00:57:22 +0000301# XXX 13 Dec 2002 KBK Not used currently
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000302# def saved_change_hook(self):
303# "Extend base method - clear breaks if module is modified"
304# if not self.get_saved():
305# self.clear_file_breaks()
306# EditorWindow.saved_change_hook(self)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000307
308 def _close(self):
309 "Extend base method - clear breaks when module is closed"
310 self.clear_file_breaks()
311 EditorWindow._close(self)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000312
David Scherer7aced172000-08-15 01:13:23 +0000313
314class PyShellFileList(FileList):
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000315 "Extend base class: IDLE supports a shell and breakpoints"
David Scherer7aced172000-08-15 01:13:23 +0000316
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000317 # override FileList's class variable, instances return PyShellEditorWindow
318 # instead of EditorWindow when new edit windows are created.
David Scherer7aced172000-08-15 01:13:23 +0000319 EditorWindow = PyShellEditorWindow
320
321 pyshell = None
322
323 def open_shell(self, event=None):
324 if self.pyshell:
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000325 self.pyshell.top.wakeup()
David Scherer7aced172000-08-15 01:13:23 +0000326 else:
327 self.pyshell = PyShell(self)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000328 if self.pyshell:
329 if not self.pyshell.begin():
330 return None
David Scherer7aced172000-08-15 01:13:23 +0000331 return self.pyshell
332
333
334class ModifiedColorDelegator(ColorDelegator):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000335 "Extend base class: colorizer for the shell window itself"
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000336
Steven M. Gavab77d3432002-03-02 07:16:21 +0000337 def __init__(self):
338 ColorDelegator.__init__(self)
339 self.LoadTagDefs()
David Scherer7aced172000-08-15 01:13:23 +0000340
341 def recolorize_main(self):
342 self.tag_remove("TODO", "1.0", "iomark")
343 self.tag_add("SYNC", "1.0", "iomark")
344 ColorDelegator.recolorize_main(self)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000345
Steven M. Gavab77d3432002-03-02 07:16:21 +0000346 def LoadTagDefs(self):
347 ColorDelegator.LoadTagDefs(self)
348 theme = idleConf.GetOption('main','Theme','name')
349 self.tagdefs.update({
350 "stdin": {'background':None,'foreground':None},
351 "stdout": idleConf.GetHighlight(theme, "stdout"),
352 "stderr": idleConf.GetHighlight(theme, "stderr"),
353 "console": idleConf.GetHighlight(theme, "console"),
Steven M. Gavab77d3432002-03-02 07:16:21 +0000354 })
David Scherer7aced172000-08-15 01:13:23 +0000355
Ned Deily5e247b72012-05-31 09:17:29 -0700356 def removecolors(self):
357 # Don't remove shell color tags before "iomark"
358 for tag in self.tagdefs:
359 self.tag_remove(tag, "iomark", "end")
360
David Scherer7aced172000-08-15 01:13:23 +0000361class ModifiedUndoDelegator(UndoDelegator):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000362 "Extend base class: forbid insert/delete before the I/O mark"
David Scherer7aced172000-08-15 01:13:23 +0000363
364 def insert(self, index, chars, tags=None):
365 try:
366 if self.delegate.compare(index, "<", "iomark"):
367 self.delegate.bell()
368 return
369 except TclError:
370 pass
371 UndoDelegator.insert(self, index, chars, tags)
372
373 def delete(self, index1, index2=None):
374 try:
375 if self.delegate.compare(index1, "<", "iomark"):
376 self.delegate.bell()
377 return
378 except TclError:
379 pass
380 UndoDelegator.delete(self, index1, index2)
381
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000382
383class MyRPCClient(rpc.RPCClient):
384
385 def handle_EOF(self):
386 "Override the base class - just re-raise EOFError"
387 raise EOFError
388
Kurt B. Kaiser8d1f11b2003-05-26 22:20:34 +0000389
David Scherer7aced172000-08-15 01:13:23 +0000390class ModifiedInterpreter(InteractiveInterpreter):
391
392 def __init__(self, tkconsole):
393 self.tkconsole = tkconsole
394 locals = sys.modules['__main__'].__dict__
395 InteractiveInterpreter.__init__(self, locals=locals)
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000396 self.save_warnings_filters = None
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000397 self.restarting = False
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +0000398 self.subprocess_arglist = None
399 self.port = PORT
Ned Deily86d669b2011-10-30 19:58:04 -0700400 self.original_compiler_flags = self.compile.compiler.flags
David Scherer7aced172000-08-15 01:13:23 +0000401
Roger Serwy16ce43a2013-06-11 22:13:17 -0500402 _afterid = None
Chui Tey5d2af632002-05-26 13:36:41 +0000403 rpcclt = None
404 rpcpid = None
405
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000406 def spawn_subprocess(self):
Florent Xiclunac8a730b2010-03-25 20:32:07 +0000407 if self.subprocess_arglist is None:
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +0000408 self.subprocess_arglist = self.build_subprocess_arglist()
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000409 args = self.subprocess_arglist
Kurt B. Kaiserb7855182003-08-14 14:54:28 +0000410 self.rpcpid = os.spawnv(os.P_NOWAIT, sys.executable, args)
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000411
Tony Lowndsf53dec22002-12-20 04:24:43 +0000412 def build_subprocess_arglist(self):
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +0000413 assert (self.port!=0), (
414 "Socket should have been assigned a port number.")
Tony Lownds2398d572003-05-13 15:28:21 +0000415 w = ['-W' + s for s in sys.warnoptions]
Georg Brandld0761532006-10-12 07:57:21 +0000416 if 1/2 > 0: # account for new division
417 w.append('-Qnew')
Tony Lownds2398d572003-05-13 15:28:21 +0000418 # Maybe IDLE is installed and is being accessed via sys.path,
419 # or maybe it's not installed and the idle.py script is being
420 # run from the IDLE source directory.
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000421 del_exitf = idleConf.GetOption('main', 'General', 'delete-exitfunc',
422 default=False, type='bool')
Tony Lownds2398d572003-05-13 15:28:21 +0000423 if __name__ == 'idlelib.PyShell':
Walter Dörwald70a6b492004-02-12 17:35:32 +0000424 command = "__import__('idlelib.run').run.main(%r)" % (del_exitf,)
Tony Lowndsf2324b92002-09-29 00:34:10 +0000425 else:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000426 command = "__import__('run').main(%r)" % (del_exitf,)
Kurt B. Kaiserb7855182003-08-14 14:54:28 +0000427 if sys.platform[:3] == 'win' and ' ' in sys.executable:
428 # handle embedded space in path by quoting the argument
429 decorated_exec = '"%s"' % sys.executable
430 else:
431 decorated_exec = sys.executable
432 return [decorated_exec] + w + ["-c", command, str(self.port)]
Tony Lowndsf2324b92002-09-29 00:34:10 +0000433
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000434 def start_subprocess(self):
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +0000435 addr = (HOST, self.port)
436 # GUI makes several attempts to acquire socket, listens for connection
Kurt B. Kaiser5db48432003-05-15 03:40:51 +0000437 for i in range(3):
Chui Tey5d2af632002-05-26 13:36:41 +0000438 time.sleep(i)
439 try:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000440 self.rpcclt = MyRPCClient(addr)
Chui Tey5d2af632002-05-26 13:36:41 +0000441 break
Terry Jan Reedy2b149862013-06-29 00:59:34 -0400442 except socket.error as err:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000443 pass
Chui Tey5d2af632002-05-26 13:36:41 +0000444 else:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000445 self.display_port_binding_error()
446 return None
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +0000447 # if PORT was 0, system will assign an 'ephemeral' port. Find it out:
448 self.port = self.rpcclt.listening_sock.getsockname()[1]
449 # if PORT was not 0, probably working with a remote execution server
450 if PORT != 0:
451 # To allow reconnection within the 2MSL wait (cf. Stevens TCP
452 # V1, 18.6), set SO_REUSEADDR. Note that this can be problematic
453 # on Windows since the implementation allows two active sockets on
454 # the same address!
455 self.rpcclt.listening_sock.setsockopt(socket.SOL_SOCKET,
456 socket.SO_REUSEADDR, 1)
457 self.spawn_subprocess()
458 #time.sleep(20) # test to simulate GUI not accepting connection
Kurt B. Kaiserb4179362002-07-26 00:06:42 +0000459 # Accept the connection from the Python execution server
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000460 self.rpcclt.listening_sock.settimeout(10)
461 try:
462 self.rpcclt.accept()
Terry Jan Reedy2b149862013-06-29 00:59:34 -0400463 except socket.timeout as err:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000464 self.display_no_subprocess_error()
465 return None
Serhiy Storchaka9abc8302013-01-25 15:30:35 +0200466 self.rpcclt.register("console", self.tkconsole)
467 self.rpcclt.register("stdin", self.tkconsole.stdin)
Kurt B. Kaiser969de452002-06-12 03:28:57 +0000468 self.rpcclt.register("stdout", self.tkconsole.stdout)
469 self.rpcclt.register("stderr", self.tkconsole.stderr)
Chui Tey5d2af632002-05-26 13:36:41 +0000470 self.rpcclt.register("flist", self.tkconsole.flist)
Kurt B. Kaiser8cd0def2003-01-31 05:06:43 +0000471 self.rpcclt.register("linecache", linecache)
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000472 self.rpcclt.register("interp", self)
Terry Jan Reedyb98000a2012-01-31 02:09:25 -0500473 self.transfer_path(with_cwd=True)
Chui Tey5d2af632002-05-26 13:36:41 +0000474 self.poll_subprocess()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000475 return self.rpcclt
Chui Tey5d2af632002-05-26 13:36:41 +0000476
Terry Jan Reedyb98000a2012-01-31 02:09:25 -0500477 def restart_subprocess(self, with_cwd=False):
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000478 if self.restarting:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000479 return self.rpcclt
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000480 self.restarting = True
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000481 # close only the subprocess debugger
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000482 debug = self.getdebugger()
483 if debug:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000484 try:
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000485 # Only close subprocess debugger, don't unregister gui_adap!
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000486 RemoteDebugger.close_subprocess_debugger(self.rpcclt)
487 except:
488 pass
489 # Kill subprocess, spawn a new one, accept connection.
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000490 self.rpcclt.close()
491 self.unix_terminate()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000492 console = self.tkconsole
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000493 was_executing = console.executing
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000494 console.executing = False
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000495 self.spawn_subprocess()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000496 try:
497 self.rpcclt.accept()
Terry Jan Reedy2b149862013-06-29 00:59:34 -0400498 except socket.timeout as err:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000499 self.display_no_subprocess_error()
500 return None
Terry Jan Reedyb98000a2012-01-31 02:09:25 -0500501 self.transfer_path(with_cwd=with_cwd)
Roger Serwyad8cad32013-04-03 00:42:24 -0500502 console.stop_readline()
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000503 # annotate restart in shell window and mark it
Kurt B. Kaiser4cc5ef52003-01-22 00:23:23 +0000504 console.text.delete("iomark", "end-1c")
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000505 if was_executing:
506 console.write('\n')
507 console.showprompt()
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000508 halfbar = ((int(console.width) - 16) // 2) * '='
509 console.write(halfbar + ' RESTART ' + halfbar)
510 console.text.mark_set("restart", "end-1c")
511 console.text.mark_gravity("restart", "left")
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000512 console.showprompt()
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000513 # restart subprocess debugger
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000514 if debug:
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000515 # Restarted debugger connects to current instance of debug GUI
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000516 gui = RemoteDebugger.restart_subprocess_debugger(self.rpcclt)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000517 # reload remote debugger breakpoints for all PyShellEditWindows
518 debug.load_breakpoints()
Ned Deily86d669b2011-10-30 19:58:04 -0700519 self.compile.compiler.flags = self.original_compiler_flags
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000520 self.restarting = False
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000521 return self.rpcclt
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000522
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000523 def __request_interrupt(self):
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000524 self.rpcclt.remotecall("exec", "interrupt_the_server", (), {})
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000525
526 def interrupt_subprocess(self):
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000527 threading.Thread(target=self.__request_interrupt).start()
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000528
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000529 def kill_subprocess(self):
Roger Serwy16ce43a2013-06-11 22:13:17 -0500530 if self._afterid is not None:
531 self.tkconsole.text.after_cancel(self._afterid)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000532 try:
533 self.rpcclt.close()
534 except AttributeError: # no socket
535 pass
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000536 self.unix_terminate()
537 self.tkconsole.executing = False
538 self.rpcclt = None
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000539
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000540 def unix_terminate(self):
541 "UNIX: make sure subprocess is terminated and collect status"
542 if hasattr(os, 'kill'):
543 try:
544 os.kill(self.rpcpid, SIGTERM)
545 except OSError:
546 # process already terminated:
547 return
548 else:
549 try:
550 os.waitpid(self.rpcpid, 0)
551 except OSError:
552 return
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000553
Terry Jan Reedyb98000a2012-01-31 02:09:25 -0500554 def transfer_path(self, with_cwd=False):
555 if with_cwd: # Issue 13506
556 path = [''] # include Current Working Directory
557 path.extend(sys.path)
558 else:
559 path = sys.path
Terry Jan Reedy1d4ae482012-01-31 02:55:32 -0500560
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000561 self.runcommand("""if 1:
562 import sys as _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +0000563 _sys.path = %r
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000564 del _sys
Terry Jan Reedyb98000a2012-01-31 02:09:25 -0500565 \n""" % (path,))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000566
Chui Tey5d2af632002-05-26 13:36:41 +0000567 active_seq = None
568
569 def poll_subprocess(self):
570 clt = self.rpcclt
571 if clt is None:
572 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000573 try:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000574 response = clt.pollresponse(self.active_seq, wait=0.05)
575 except (EOFError, IOError, KeyboardInterrupt):
576 # lost connection or subprocess terminated itself, restart
577 # [the KBI is from rpc.SocketIO.handle_EOF()]
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000578 if self.tkconsole.closing:
579 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000580 response = None
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000581 self.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000582 if response:
583 self.tkconsole.resetoutput()
584 self.active_seq = None
585 how, what = response
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000586 console = self.tkconsole.console
Chui Tey5d2af632002-05-26 13:36:41 +0000587 if how == "OK":
588 if what is not None:
Terry Jan Reedybee003c2014-09-19 22:37:24 -0400589 print(repr(what), file=console)
Chui Tey5d2af632002-05-26 13:36:41 +0000590 elif how == "EXCEPTION":
Chui Tey5d2af632002-05-26 13:36:41 +0000591 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
592 self.remote_stack_viewer()
593 elif how == "ERROR":
Kurt B. Kaiser0930c432002-12-06 21:45:24 +0000594 errmsg = "PyShell.ModifiedInterpreter: Subprocess ERROR:\n"
Terry Jan Reedybee003c2014-09-19 22:37:24 -0400595 print(errmsg, what, file=sys.__stderr__)
596 print(errmsg, what, file=console)
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000597 # we received a response to the currently active seq number:
Kurt B. Kaiserd112bc72006-08-16 05:01:42 +0000598 try:
599 self.tkconsole.endexecuting()
600 except AttributeError: # shell may have closed
601 pass
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000602 # Reschedule myself
603 if not self.tkconsole.closing:
Roger Serwy16ce43a2013-06-11 22:13:17 -0500604 self._afterid = self.tkconsole.text.after(
605 self.tkconsole.pollinterval, self.poll_subprocess)
Chui Tey5d2af632002-05-26 13:36:41 +0000606
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000607 debugger = None
608
609 def setdebugger(self, debugger):
610 self.debugger = debugger
611
612 def getdebugger(self):
613 return self.debugger
614
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000615 def open_remote_stack_viewer(self):
616 """Initiate the remote stack viewer from a separate thread.
617
618 This method is called from the subprocess, and by returning from this
619 method we allow the subprocess to unblock. After a bit the shell
620 requests the subprocess to open the remote stack viewer which returns a
Ezio Melottic569cfe2010-07-23 16:55:21 +0000621 static object looking at the last exception. It is queried through
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000622 the RPC mechanism.
623
624 """
625 self.tkconsole.text.after(300, self.remote_stack_viewer)
626 return
627
Chui Tey5d2af632002-05-26 13:36:41 +0000628 def remote_stack_viewer(self):
Florent Xiclunad630c042010-04-02 07:24:52 +0000629 from idlelib import RemoteObjectBrowser
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000630 oid = self.rpcclt.remotequeue("exec", "stackviewer", ("flist",), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000631 if oid is None:
632 self.tkconsole.root.bell()
633 return
634 item = RemoteObjectBrowser.StubObjectTreeItem(self.rpcclt, oid)
Florent Xiclunad630c042010-04-02 07:24:52 +0000635 from idlelib.TreeWidget import ScrolledCanvas, TreeNode
Chui Tey5d2af632002-05-26 13:36:41 +0000636 top = Toplevel(self.tkconsole.root)
Kurt B. Kaiser73360a32004-03-08 18:15:31 +0000637 theme = idleConf.GetOption('main','Theme','name')
638 background = idleConf.GetHighlight(theme, 'normal')['background']
639 sc = ScrolledCanvas(top, bg=background, highlightthickness=0)
Chui Tey5d2af632002-05-26 13:36:41 +0000640 sc.frame.pack(expand=1, fill="both")
641 node = TreeNode(sc.canvas, None, item)
642 node.expand()
643 # XXX Should GC the remote tree when closing the window
644
David Scherer7aced172000-08-15 01:13:23 +0000645 gid = 0
646
647 def execsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000648 "Like runsource() but assumes complete exec source"
David Scherer7aced172000-08-15 01:13:23 +0000649 filename = self.stuffsource(source)
650 self.execfile(filename, source)
651
652 def execfile(self, filename, source=None):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000653 "Execute an existing file"
David Scherer7aced172000-08-15 01:13:23 +0000654 if source is None:
655 source = open(filename, "r").read()
656 try:
657 code = compile(source, filename, "exec")
658 except (OverflowError, SyntaxError):
659 self.tkconsole.resetoutput()
Terry Jan Reedybee003c2014-09-19 22:37:24 -0400660 print('*** Error in script or command!\n'
661 'Traceback (most recent call last):',
662 file=self.tkconsole.stderr)
David Scherer7aced172000-08-15 01:13:23 +0000663 InteractiveInterpreter.showsyntaxerror(self, filename)
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000664 self.tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000665 else:
666 self.runcode(code)
667
668 def runsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000669 "Extend base class method: Stuff the source in the line cache first"
David Scherer7aced172000-08-15 01:13:23 +0000670 filename = self.stuffsource(source)
671 self.more = 0
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000672 self.save_warnings_filters = warnings.filters[:]
673 warnings.filterwarnings(action="error", category=SyntaxWarning)
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000674 if isinstance(source, types.UnicodeType):
Florent Xiclunad630c042010-04-02 07:24:52 +0000675 from idlelib import IOBinding
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000676 try:
677 source = source.encode(IOBinding.encoding)
678 except UnicodeError:
679 self.tkconsole.resetoutput()
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +0000680 self.write("Unsupported characters in input\n")
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000681 return
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000682 try:
Kurt B. Kaiser935ea9a2005-05-10 03:44:24 +0000683 # InteractiveInterpreter.runsource() calls its runcode() method,
684 # which is overridden (see below)
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000685 return InteractiveInterpreter.runsource(self, source, filename)
686 finally:
687 if self.save_warnings_filters is not None:
688 warnings.filters[:] = self.save_warnings_filters
689 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000690
691 def stuffsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000692 "Stuff source in the filename cache"
David Scherer7aced172000-08-15 01:13:23 +0000693 filename = "<pyshell#%d>" % self.gid
694 self.gid = self.gid + 1
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000695 lines = source.split("\n")
David Scherer7aced172000-08-15 01:13:23 +0000696 linecache.cache[filename] = len(source)+1, 0, lines, filename
697 return filename
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000698
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000699 def prepend_syspath(self, filename):
700 "Prepend sys.path with file's directory if not already included"
701 self.runcommand("""if 1:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000702 _filename = %r
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000703 import sys as _sys
704 from os.path import dirname as _dirname
705 _dir = _dirname(_filename)
706 if not _dir in _sys.path:
707 _sys.path.insert(0, _dir)
708 del _filename, _sys, _dirname, _dir
Walter Dörwald70a6b492004-02-12 17:35:32 +0000709 \n""" % (filename,))
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000710
David Scherer7aced172000-08-15 01:13:23 +0000711 def showsyntaxerror(self, filename=None):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000712 """Extend base class method: Add Colorizing
713
714 Color the offending position instead of printing it and pointing at it
715 with a caret.
716
717 """
David Scherer7aced172000-08-15 01:13:23 +0000718 text = self.tkconsole.text
719 stuff = self.unpackerror()
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000720 if stuff:
721 msg, lineno, offset, line = stuff
722 if lineno == 1:
723 pos = "iomark + %d chars" % (offset-1)
724 else:
725 pos = "iomark linestart + %d lines + %d chars" % \
726 (lineno-1, offset-1)
727 text.tag_add("ERROR", pos)
728 text.see(pos)
729 char = text.get(pos)
730 if char and char in IDENTCHARS:
731 text.tag_add("ERROR", pos + " wordstart", pos)
732 self.tkconsole.resetoutput()
733 self.write("SyntaxError: %s\n" % str(msg))
734 else:
David Scherer7aced172000-08-15 01:13:23 +0000735 self.tkconsole.resetoutput()
736 InteractiveInterpreter.showsyntaxerror(self, filename)
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000737 self.tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000738
739 def unpackerror(self):
740 type, value, tb = sys.exc_info()
741 ok = type is SyntaxError
742 if ok:
743 try:
744 msg, (dummy_filename, lineno, offset, line) = value
Kurt B. Kaiserbea57c62003-07-09 04:27:24 +0000745 if not offset:
746 offset = 0
David Scherer7aced172000-08-15 01:13:23 +0000747 except:
748 ok = 0
749 if ok:
750 return msg, lineno, offset, line
751 else:
752 return None
753
754 def showtraceback(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000755 "Extend base class method to reset output properly"
David Scherer7aced172000-08-15 01:13:23 +0000756 self.tkconsole.resetoutput()
757 self.checklinecache()
758 InteractiveInterpreter.showtraceback(self)
Chui Tey5d2af632002-05-26 13:36:41 +0000759 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
760 self.tkconsole.open_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +0000761
762 def checklinecache(self):
763 c = linecache.cache
764 for key in c.keys():
765 if key[:1] + key[-1:] != "<>":
766 del c[key]
767
Chui Tey5d2af632002-05-26 13:36:41 +0000768 def runcommand(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000769 "Run the code without invoking the debugger"
Chui Tey5d2af632002-05-26 13:36:41 +0000770 # The code better not raise an exception!
771 if self.tkconsole.executing:
Neal Norwitzf4c4f112002-11-30 18:49:10 +0000772 self.display_executing_dialog()
Chui Tey5d2af632002-05-26 13:36:41 +0000773 return 0
774 if self.rpcclt:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000775 self.rpcclt.remotequeue("exec", "runcode", (code,), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000776 else:
777 exec code in self.locals
778 return 1
779
David Scherer7aced172000-08-15 01:13:23 +0000780 def runcode(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000781 "Override base class method"
Chui Tey5d2af632002-05-26 13:36:41 +0000782 if self.tkconsole.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000783 self.interp.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000784 self.checklinecache()
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000785 if self.save_warnings_filters is not None:
786 warnings.filters[:] = self.save_warnings_filters
787 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000788 debugger = self.debugger
789 try:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000790 self.tkconsole.beginexecuting()
Kurt B. Kaiserdddeb0e2007-02-06 03:21:40 +0000791 if not debugger and self.rpcclt is not None:
792 self.active_seq = self.rpcclt.asyncqueue("exec", "runcode",
793 (code,), {})
794 elif debugger:
795 debugger.run(code, self.locals)
796 else:
797 exec code in self.locals
798 except SystemExit:
799 if not self.tkconsole.closing:
800 if tkMessageBox.askyesno(
801 "Exit?",
802 "Do you want to exit altogether?",
803 default="yes",
804 master=self.tkconsole.text):
Kurt B. Kaiserf137e1d2006-08-16 07:04:17 +0000805 raise
Kurt B. Kaiserdddeb0e2007-02-06 03:21:40 +0000806 else:
807 self.showtraceback()
808 else:
809 raise
810 except:
811 if use_subprocess:
Terry Jan Reedybee003c2014-09-19 22:37:24 -0400812 print("IDLE internal error in runcode()",
813 file=self.tkconsole.stderr)
David Scherer7aced172000-08-15 01:13:23 +0000814 self.showtraceback()
Kurt B. Kaiserdddeb0e2007-02-06 03:21:40 +0000815 self.tkconsole.endexecuting()
816 else:
817 if self.tkconsole.canceled:
818 self.tkconsole.canceled = False
Terry Jan Reedybee003c2014-09-19 22:37:24 -0400819 print("KeyboardInterrupt", file=self.tkconsole.stderr)
Kurt B. Kaiserdddeb0e2007-02-06 03:21:40 +0000820 else:
821 self.showtraceback()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000822 finally:
823 if not use_subprocess:
Kurt B. Kaiserd112bc72006-08-16 05:01:42 +0000824 try:
825 self.tkconsole.endexecuting()
826 except AttributeError: # shell may have closed
827 pass
David Scherer7aced172000-08-15 01:13:23 +0000828
829 def write(self, s):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000830 "Override base class method"
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000831 self.tkconsole.stderr.write(s)
David Scherer7aced172000-08-15 01:13:23 +0000832
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000833 def display_port_binding_error(self):
834 tkMessageBox.showerror(
835 "Port Binding Error",
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +0000836 "IDLE can't bind to a TCP/IP port, which is necessary to "
837 "communicate with its Python execution server. This might be "
838 "because no networking is installed on this computer. "
839 "Run IDLE with the -n command line switch to start without a "
840 "subprocess and refer to Help/IDLE Help 'Running without a "
841 "subprocess' for further details.",
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000842 master=self.tkconsole.text)
843
844 def display_no_subprocess_error(self):
845 tkMessageBox.showerror(
846 "Subprocess Startup Error",
847 "IDLE's subprocess didn't make connection. Either IDLE can't "
848 "start a subprocess or personal firewall software is blocking "
849 "the connection.",
850 master=self.tkconsole.text)
851
852 def display_executing_dialog(self):
853 tkMessageBox.showerror(
854 "Already executing",
855 "The Python Shell window is already executing a command; "
856 "please wait until it is finished.",
857 master=self.tkconsole.text)
858
859
David Scherer7aced172000-08-15 01:13:23 +0000860class PyShell(OutputWindow):
861
Terry Jan Reedyd676a3a2013-03-30 18:50:43 -0400862 shell_title = "Python " + python_version() + " Shell"
David Scherer7aced172000-08-15 01:13:23 +0000863
864 # Override classes
865 ColorDelegator = ModifiedColorDelegator
866 UndoDelegator = ModifiedUndoDelegator
867
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000868 # Override menus
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000869 menu_specs = [
870 ("file", "_File"),
871 ("edit", "_Edit"),
Kurt B. Kaiser4cc5ef52003-01-22 00:23:23 +0000872 ("debug", "_Debug"),
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000873 ("options", "_Options"),
Ned Deilyb5daa3d2015-01-17 21:03:41 -0800874 ("windows", "_Window"),
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000875 ("help", "_Help"),
876 ]
David Scherer7aced172000-08-15 01:13:23 +0000877
Ronald Oussoren19302d92006-06-11 14:33:36 +0000878
David Scherer7aced172000-08-15 01:13:23 +0000879 # New classes
Florent Xiclunad630c042010-04-02 07:24:52 +0000880 from idlelib.IdleHistory import History
David Scherer7aced172000-08-15 01:13:23 +0000881
882 def __init__(self, flist=None):
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000883 if use_subprocess:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000884 ms = self.menu_specs
885 if ms[2][0] != "shell":
Kurt B. Kaiser7ae35482006-08-16 21:45:59 +0000886 ms.insert(2, ("shell", "She_ll"))
David Scherer7aced172000-08-15 01:13:23 +0000887 self.interp = ModifiedInterpreter(self)
888 if flist is None:
889 root = Tk()
890 fixwordbreaks(root)
891 root.withdraw()
892 flist = PyShellFileList(root)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000893 #
David Scherer7aced172000-08-15 01:13:23 +0000894 OutputWindow.__init__(self, flist, None, None)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000895 #
Kurt B. Kaiser6af44982005-01-19 00:22:59 +0000896## self.config(usetabs=1, indentwidth=8, context_use_ps1=1)
897 self.usetabs = True
898 # indentwidth must be 8 when using tabs. See note in EditorWindow:
899 self.indentwidth = 8
900 self.context_use_ps1 = True
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000901 #
David Scherer7aced172000-08-15 01:13:23 +0000902 text = self.text
903 text.configure(wrap="char")
904 text.bind("<<newline-and-indent>>", self.enter_callback)
905 text.bind("<<plain-newline-and-indent>>", self.linefeed_callback)
906 text.bind("<<interrupt-execution>>", self.cancel_callback)
David Scherer7aced172000-08-15 01:13:23 +0000907 text.bind("<<end-of-file>>", self.eof_callback)
908 text.bind("<<open-stack-viewer>>", self.open_stack_viewer)
Kurt B. Kaiser57bfe5d2003-05-10 00:09:52 +0000909 text.bind("<<toggle-debugger>>", self.toggle_debugger)
David Scherer7aced172000-08-15 01:13:23 +0000910 text.bind("<<toggle-jit-stack-viewer>>", self.toggle_jit_stack_viewer)
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000911 if use_subprocess:
912 text.bind("<<view-restart>>", self.view_restart_mark)
913 text.bind("<<restart-shell>>", self.restart_shell)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000914 #
David Scherer7aced172000-08-15 01:13:23 +0000915 self.save_stdout = sys.stdout
916 self.save_stderr = sys.stderr
917 self.save_stdin = sys.stdin
Florent Xiclunad630c042010-04-02 07:24:52 +0000918 from idlelib import IOBinding
Serhiy Storchaka9abc8302013-01-25 15:30:35 +0200919 self.stdin = PseudoInputFile(self, "stdin", IOBinding.encoding)
920 self.stdout = PseudoOutputFile(self, "stdout", IOBinding.encoding)
921 self.stderr = PseudoOutputFile(self, "stderr", IOBinding.encoding)
922 self.console = PseudoOutputFile(self, "console", IOBinding.encoding)
Chui Tey5d2af632002-05-26 13:36:41 +0000923 if not use_subprocess:
924 sys.stdout = self.stdout
925 sys.stderr = self.stderr
Martin v. Löwise2b56242012-07-25 10:56:22 +0200926 sys.stdin = self.stdin
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000927 #
David Scherer7aced172000-08-15 01:13:23 +0000928 self.history = self.History(self.text)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000929 #
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000930 self.pollinterval = 50 # millisec
Chui Tey5d2af632002-05-26 13:36:41 +0000931
Kurt B. Kaiser4d5bc602004-06-06 01:29:22 +0000932 def get_standard_extension_names(self):
933 return idleConf.GetExtensions(shell_only=True)
934
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000935 reading = False
936 executing = False
937 canceled = False
938 endoffile = False
939 closing = False
Roger Serwyad8cad32013-04-03 00:42:24 -0500940 _stop_readline_flag = False
David Scherer7aced172000-08-15 01:13:23 +0000941
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +0000942 def set_warning_stream(self, stream):
Skip Montanarod9161422004-07-06 21:53:27 +0000943 global warning_stream
944 warning_stream = stream
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +0000945
946 def get_warning_stream(self):
947 return warning_stream
948
David Scherer7aced172000-08-15 01:13:23 +0000949 def toggle_debugger(self, event=None):
950 if self.executing:
951 tkMessageBox.showerror("Don't debug now",
952 "You can only toggle the debugger when idle",
953 master=self.text)
954 self.set_debugger_indicator()
955 return "break"
956 else:
957 db = self.interp.getdebugger()
958 if db:
959 self.close_debugger()
960 else:
961 self.open_debugger()
962
963 def set_debugger_indicator(self):
964 db = self.interp.getdebugger()
965 self.setvar("<<toggle-debugger>>", not not db)
966
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000967 def toggle_jit_stack_viewer(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +0000968 pass # All we need is the variable
969
970 def close_debugger(self):
971 db = self.interp.getdebugger()
972 if db:
973 self.interp.setdebugger(None)
974 db.close()
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000975 if self.interp.rpcclt:
976 RemoteDebugger.close_remote_debugger(self.interp.rpcclt)
David Scherer7aced172000-08-15 01:13:23 +0000977 self.resetoutput()
978 self.console.write("[DEBUG OFF]\n")
979 sys.ps1 = ">>> "
980 self.showprompt()
981 self.set_debugger_indicator()
982
983 def open_debugger(self):
Chui Tey5d2af632002-05-26 13:36:41 +0000984 if self.interp.rpcclt:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000985 dbg_gui = RemoteDebugger.start_remote_debugger(self.interp.rpcclt,
986 self)
987 else:
988 dbg_gui = Debugger.Debugger(self)
989 self.interp.setdebugger(dbg_gui)
990 dbg_gui.load_breakpoints()
Chui Tey5d2af632002-05-26 13:36:41 +0000991 sys.ps1 = "[DEBUG ON]\n>>> "
992 self.showprompt()
993 self.set_debugger_indicator()
994
David Scherer7aced172000-08-15 01:13:23 +0000995 def beginexecuting(self):
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000996 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +0000997 self.resetoutput()
998 self.executing = 1
David Scherer7aced172000-08-15 01:13:23 +0000999
1000 def endexecuting(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +00001001 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +00001002 self.executing = 0
1003 self.canceled = 0
Chui Tey5d2af632002-05-26 13:36:41 +00001004 self.showprompt()
David Scherer7aced172000-08-15 01:13:23 +00001005
1006 def close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +00001007 "Extend EditorWindow.close()"
David Scherer7aced172000-08-15 01:13:23 +00001008 if self.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001009 response = tkMessageBox.askokcancel(
David Scherer7aced172000-08-15 01:13:23 +00001010 "Kill?",
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001011 "The program is still running!\n Do you want to kill it?",
David Scherer7aced172000-08-15 01:13:23 +00001012 default="ok",
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001013 parent=self.text)
Benjamin Peterson5b63acd2008-03-29 15:24:25 +00001014 if response is False:
David Scherer7aced172000-08-15 01:13:23 +00001015 return "cancel"
Roger Serwyad8cad32013-04-03 00:42:24 -05001016 self.stop_readline()
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001017 self.canceled = True
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +00001018 self.closing = True
Kurt B. Kaiser88957d82003-05-19 23:11:51 +00001019 return EditorWindow.close(self)
David Scherer7aced172000-08-15 01:13:23 +00001020
1021 def _close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +00001022 "Extend EditorWindow._close(), shut down debugger and execution server"
David Scherer7aced172000-08-15 01:13:23 +00001023 self.close_debugger()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001024 if use_subprocess:
1025 self.interp.kill_subprocess()
David Scherer7aced172000-08-15 01:13:23 +00001026 # Restore std streams
1027 sys.stdout = self.save_stdout
1028 sys.stderr = self.save_stderr
1029 sys.stdin = self.save_stdin
1030 # Break cycles
1031 self.interp = None
1032 self.console = None
David Scherer7aced172000-08-15 01:13:23 +00001033 self.flist.pyshell = None
1034 self.history = None
Kurt B. Kaiser83118c62002-06-24 17:03:37 +00001035 EditorWindow._close(self)
David Scherer7aced172000-08-15 01:13:23 +00001036
1037 def ispythonsource(self, filename):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +00001038 "Override EditorWindow method: never remove the colorizer"
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001039 return True
David Scherer7aced172000-08-15 01:13:23 +00001040
1041 def short_title(self):
1042 return self.shell_title
1043
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +00001044 COPYRIGHT = \
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001045 'Type "copyright", "credits" or "license()" for more information.'
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +00001046
David Scherer7aced172000-08-15 01:13:23 +00001047 def begin(self):
1048 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001049 if use_subprocess:
1050 nosub = ''
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001051 client = self.interp.start_subprocess()
1052 if not client:
1053 self.close()
Kurt B. Kaiser76637292004-01-21 22:10:01 +00001054 return False
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001055 else:
1056 nosub = "==== No Subprocess ===="
Raymond Hettingerbf3f69e2009-01-26 23:29:09 +00001057 self.write("Python %s on %s\n%s\n%s" %
1058 (sys.version, sys.platform, self.COPYRIGHT, nosub))
David Scherer7aced172000-08-15 01:13:23 +00001059 self.showprompt()
Georg Brandl6634bf22008-05-20 07:13:37 +00001060 import Tkinter
1061 Tkinter._default_root = None # 03Jan04 KBK What's this?
Kurt B. Kaiser76637292004-01-21 22:10:01 +00001062 return True
David Scherer7aced172000-08-15 01:13:23 +00001063
Roger Serwyad8cad32013-04-03 00:42:24 -05001064 def stop_readline(self):
1065 if not self.reading: # no nested mainloop to exit.
1066 return
1067 self._stop_readline_flag = True
1068 self.top.quit()
1069
David Scherer7aced172000-08-15 01:13:23 +00001070 def readline(self):
1071 save = self.reading
1072 try:
1073 self.reading = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001074 self.top.mainloop() # nested mainloop()
David Scherer7aced172000-08-15 01:13:23 +00001075 finally:
1076 self.reading = save
Roger Serwyad8cad32013-04-03 00:42:24 -05001077 if self._stop_readline_flag:
1078 self._stop_readline_flag = False
1079 return ""
David Scherer7aced172000-08-15 01:13:23 +00001080 line = self.text.get("iomark", "end-1c")
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001081 if len(line) == 0: # may be EOF if we quit our mainloop with Ctrl-C
1082 line = "\n"
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001083 if isinstance(line, unicode):
Florent Xiclunad630c042010-04-02 07:24:52 +00001084 from idlelib import IOBinding
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001085 try:
1086 line = line.encode(IOBinding.encoding)
1087 except UnicodeError:
1088 pass
David Scherer7aced172000-08-15 01:13:23 +00001089 self.resetoutput()
1090 if self.canceled:
1091 self.canceled = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001092 if not use_subprocess:
1093 raise KeyboardInterrupt
David Scherer7aced172000-08-15 01:13:23 +00001094 if self.endoffile:
1095 self.endoffile = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001096 line = ""
David Scherer7aced172000-08-15 01:13:23 +00001097 return line
1098
1099 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001100 return True
David Scherer7aced172000-08-15 01:13:23 +00001101
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001102 def cancel_callback(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +00001103 try:
1104 if self.text.compare("sel.first", "!=", "sel.last"):
1105 return # Active selection -- always use default binding
1106 except:
1107 pass
1108 if not (self.executing or self.reading):
1109 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001110 self.interp.write("KeyboardInterrupt\n")
David Scherer7aced172000-08-15 01:13:23 +00001111 self.showprompt()
1112 return "break"
1113 self.endoffile = 0
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001114 self.canceled = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001115 if (self.executing and self.interp.rpcclt):
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +00001116 if self.interp.getdebugger():
1117 self.interp.restart_subprocess()
1118 else:
1119 self.interp.interrupt_subprocess()
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001120 if self.reading:
1121 self.top.quit() # exit the nested mainloop() in readline()
David Scherer7aced172000-08-15 01:13:23 +00001122 return "break"
1123
1124 def eof_callback(self, event):
1125 if self.executing and not self.reading:
1126 return # Let the default binding (delete next char) take over
1127 if not (self.text.compare("iomark", "==", "insert") and
1128 self.text.compare("insert", "==", "end-1c")):
1129 return # Let the default binding (delete next char) take over
1130 if not self.executing:
David Scherer7aced172000-08-15 01:13:23 +00001131 self.resetoutput()
1132 self.close()
1133 else:
1134 self.canceled = 0
1135 self.endoffile = 1
1136 self.top.quit()
1137 return "break"
1138
David Scherer7aced172000-08-15 01:13:23 +00001139 def linefeed_callback(self, event):
1140 # Insert a linefeed without entering anything (still autoindented)
1141 if self.reading:
1142 self.text.insert("insert", "\n")
1143 self.text.see("insert")
1144 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001145 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001146 return "break"
1147
1148 def enter_callback(self, event):
1149 if self.executing and not self.reading:
1150 return # Let the default binding (insert '\n') take over
1151 # If some text is selected, recall the selection
1152 # (but only if this before the I/O mark)
1153 try:
1154 sel = self.text.get("sel.first", "sel.last")
1155 if sel:
1156 if self.text.compare("sel.last", "<=", "iomark"):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001157 self.recall(sel, event)
David Scherer7aced172000-08-15 01:13:23 +00001158 return "break"
1159 except:
1160 pass
1161 # If we're strictly before the line containing iomark, recall
1162 # the current line, less a leading prompt, less leading or
1163 # trailing whitespace
1164 if self.text.compare("insert", "<", "iomark linestart"):
1165 # Check if there's a relevant stdin range -- if so, use it
1166 prev = self.text.tag_prevrange("stdin", "insert")
1167 if prev and self.text.compare("insert", "<", prev[1]):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001168 self.recall(self.text.get(prev[0], prev[1]), event)
David Scherer7aced172000-08-15 01:13:23 +00001169 return "break"
1170 next = self.text.tag_nextrange("stdin", "insert")
1171 if next and self.text.compare("insert lineend", ">=", next[0]):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001172 self.recall(self.text.get(next[0], next[1]), event)
David Scherer7aced172000-08-15 01:13:23 +00001173 return "break"
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001174 # No stdin mark -- just get the current line, less any prompt
Kurt B. Kaiserb1754452005-11-18 22:05:48 +00001175 indices = self.text.tag_nextrange("console", "insert linestart")
1176 if indices and \
1177 self.text.compare(indices[0], "<=", "insert linestart"):
1178 self.recall(self.text.get(indices[1], "insert lineend"), event)
1179 else:
1180 self.recall(self.text.get("insert linestart", "insert lineend"), event)
David Scherer7aced172000-08-15 01:13:23 +00001181 return "break"
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001182 # If we're between the beginning of the line and the iomark, i.e.
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001183 # in the prompt area, move to the end of the prompt
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001184 if self.text.compare("insert", "<", "iomark"):
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001185 self.text.mark_set("insert", "iomark")
David Scherer7aced172000-08-15 01:13:23 +00001186 # If we're in the current input and there's only whitespace
1187 # beyond the cursor, erase that whitespace first
1188 s = self.text.get("insert", "end-1c")
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001189 if s and not s.strip():
David Scherer7aced172000-08-15 01:13:23 +00001190 self.text.delete("insert", "end-1c")
1191 # If we're in the current input before its last line,
1192 # insert a newline right at the insert point
1193 if self.text.compare("insert", "<", "end-1c linestart"):
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001194 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001195 return "break"
1196 # We're in the last line; append a newline and submit it
1197 self.text.mark_set("insert", "end-1c")
1198 if self.reading:
1199 self.text.insert("insert", "\n")
1200 self.text.see("insert")
1201 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001202 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001203 self.text.tag_add("stdin", "iomark", "end-1c")
1204 self.text.update_idletasks()
1205 if self.reading:
1206 self.top.quit() # Break out of recursive mainloop() in raw_input()
1207 else:
1208 self.runit()
1209 return "break"
1210
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001211 def recall(self, s, event):
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001212 # remove leading and trailing empty or whitespace lines
1213 s = re.sub(r'^\s*\n', '' , s)
1214 s = re.sub(r'\n\s*$', '', s)
1215 lines = s.split('\n')
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001216 self.text.undo_block_start()
1217 try:
1218 self.text.tag_remove("sel", "1.0", "end")
1219 self.text.mark_set("insert", "end-1c")
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001220 prefix = self.text.get("insert linestart", "insert")
1221 if prefix.rstrip().endswith(':'):
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001222 self.newline_and_indent_event(event)
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001223 prefix = self.text.get("insert linestart", "insert")
1224 self.text.insert("insert", lines[0].strip())
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001225 if len(lines) > 1:
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001226 orig_base_indent = re.search(r'^([ \t]*)', lines[0]).group(0)
1227 new_base_indent = re.search(r'^([ \t]*)', prefix).group(0)
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001228 for line in lines[1:]:
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001229 if line.startswith(orig_base_indent):
1230 # replace orig base indentation with new indentation
1231 line = new_base_indent + line[len(orig_base_indent):]
1232 self.text.insert('insert', '\n'+line.rstrip())
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001233 finally:
1234 self.text.see("insert")
1235 self.text.undo_block_stop()
David Scherer7aced172000-08-15 01:13:23 +00001236
1237 def runit(self):
1238 line = self.text.get("iomark", "end-1c")
1239 # Strip off last newline and surrounding whitespace.
1240 # (To allow you to hit return twice to end a statement.)
1241 i = len(line)
1242 while i > 0 and line[i-1] in " \t":
1243 i = i-1
1244 if i > 0 and line[i-1] == "\n":
1245 i = i-1
1246 while i > 0 and line[i-1] in " \t":
1247 i = i-1
1248 line = line[:i]
1249 more = self.interp.runsource(line)
David Scherer7aced172000-08-15 01:13:23 +00001250
David Scherer7aced172000-08-15 01:13:23 +00001251 def open_stack_viewer(self, event=None):
Chui Tey5d2af632002-05-26 13:36:41 +00001252 if self.interp.rpcclt:
1253 return self.interp.remote_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +00001254 try:
1255 sys.last_traceback
1256 except:
1257 tkMessageBox.showerror("No stack trace",
1258 "There is no stack trace yet.\n"
1259 "(sys.last_traceback is not defined)",
1260 master=self.text)
1261 return
Florent Xiclunad630c042010-04-02 07:24:52 +00001262 from idlelib.StackViewer import StackBrowser
David Scherer7aced172000-08-15 01:13:23 +00001263 sv = StackBrowser(self.root, self.flist)
1264
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001265 def view_restart_mark(self, event=None):
1266 self.text.see("iomark")
1267 self.text.see("restart")
1268
1269 def restart_shell(self, event=None):
Terry Jan Reedyb98000a2012-01-31 02:09:25 -05001270 "Callback for Run/Restart Shell Cntl-F6"
1271 self.interp.restart_subprocess(with_cwd=True)
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001272
David Scherer7aced172000-08-15 01:13:23 +00001273 def showprompt(self):
1274 self.resetoutput()
1275 try:
1276 s = str(sys.ps1)
1277 except:
1278 s = ""
1279 self.console.write(s)
1280 self.text.mark_set("insert", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001281 self.set_line_and_column()
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +00001282 self.io.reset_undo()
David Scherer7aced172000-08-15 01:13:23 +00001283
1284 def resetoutput(self):
1285 source = self.text.get("iomark", "end-1c")
1286 if self.history:
Terry Jan Reedyb638a382013-08-13 19:51:04 -04001287 self.history.store(source)
David Scherer7aced172000-08-15 01:13:23 +00001288 if self.text.get("end-2c") != "\n":
1289 self.text.insert("end-1c", "\n")
1290 self.text.mark_set("iomark", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001291 self.set_line_and_column()
David Scherer7aced172000-08-15 01:13:23 +00001292 sys.stdout.softspace = 0
1293
1294 def write(self, s, tags=()):
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001295 try:
1296 self.text.mark_gravity("iomark", "right")
1297 OutputWindow.write(self, s, tags, "iomark")
1298 self.text.mark_gravity("iomark", "left")
1299 except:
1300 pass
David Scherer7aced172000-08-15 01:13:23 +00001301 if self.canceled:
1302 self.canceled = 0
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001303 if not use_subprocess:
1304 raise KeyboardInterrupt
David Scherer7aced172000-08-15 01:13:23 +00001305
Andrew Svetlov5018db72012-11-01 22:39:14 +02001306 def rmenu_check_cut(self):
1307 try:
1308 if self.text.compare('sel.first', '<', 'iomark'):
1309 return 'disabled'
1310 except TclError: # no selection, so the index 'sel.first' doesn't exist
1311 return 'disabled'
1312 return super(PyShell, self).rmenu_check_cut()
1313
1314 def rmenu_check_paste(self):
1315 if self.text.compare('insert', '<', 'iomark'):
1316 return 'disabled'
1317 return super(PyShell, self).rmenu_check_paste()
1318
Serhiy Storchaka9abc8302013-01-25 15:30:35 +02001319class PseudoFile(io.TextIOBase):
David Scherer7aced172000-08-15 01:13:23 +00001320
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001321 def __init__(self, shell, tags, encoding=None):
David Scherer7aced172000-08-15 01:13:23 +00001322 self.shell = shell
1323 self.tags = tags
Chui Tey5d2af632002-05-26 13:36:41 +00001324 self.softspace = 0
Serhiy Storchaka9abc8302013-01-25 15:30:35 +02001325 self._encoding = encoding
David Scherer7aced172000-08-15 01:13:23 +00001326
Serhiy Storchaka9abc8302013-01-25 15:30:35 +02001327 @property
1328 def encoding(self):
1329 return self._encoding
David Scherer7aced172000-08-15 01:13:23 +00001330
Serhiy Storchaka9abc8302013-01-25 15:30:35 +02001331 @property
1332 def name(self):
1333 return '<%s>' % self.tags
David Scherer7aced172000-08-15 01:13:23 +00001334
1335 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001336 return True
David Scherer7aced172000-08-15 01:13:23 +00001337
Serhiy Storchaka9abc8302013-01-25 15:30:35 +02001338
1339class PseudoOutputFile(PseudoFile):
1340
1341 def writable(self):
1342 return True
Martin v. Löwise2b56242012-07-25 10:56:22 +02001343
1344 def write(self, s):
Serhiy Storchaka9abc8302013-01-25 15:30:35 +02001345 if self.closed:
1346 raise ValueError("write to closed file")
Serhiy Storchaka7057f3f2013-12-10 10:04:41 +02001347 if type(s) not in (unicode, str, bytearray):
1348 # See issue #19481
1349 if isinstance(s, unicode):
Serhiy Storchakaac5164d2015-03-24 19:42:15 +02001350 s = unicode.__getitem__(s, slice(None))
Serhiy Storchaka7057f3f2013-12-10 10:04:41 +02001351 elif isinstance(s, str):
1352 s = str.__str__(s)
1353 elif isinstance(s, bytearray):
1354 s = bytearray.__str__(s)
1355 else:
1356 raise TypeError('must be string, not ' + type(s).__name__)
Serhiy Storchaka9abc8302013-01-25 15:30:35 +02001357 return self.shell.write(s, self.tags)
1358
1359
1360class PseudoInputFile(PseudoFile):
1361
1362 def __init__(self, shell, tags, encoding=None):
1363 PseudoFile.__init__(self, shell, tags, encoding)
1364 self._line_buffer = ''
1365
1366 def readable(self):
1367 return True
1368
1369 def read(self, size=-1):
1370 if self.closed:
1371 raise ValueError("read from closed file")
1372 if size is None:
1373 size = -1
1374 elif not isinstance(size, int):
1375 raise TypeError('must be int, not ' + type(size).__name__)
1376 result = self._line_buffer
1377 self._line_buffer = ''
1378 if size < 0:
1379 while True:
1380 line = self.shell.readline()
1381 if not line: break
1382 result += line
1383 else:
1384 while len(result) < size:
1385 line = self.shell.readline()
1386 if not line: break
1387 result += line
1388 self._line_buffer = result[size:]
1389 result = result[:size]
1390 return result
1391
1392 def readline(self, size=-1):
1393 if self.closed:
1394 raise ValueError("read from closed file")
1395 if size is None:
1396 size = -1
1397 elif not isinstance(size, int):
1398 raise TypeError('must be int, not ' + type(size).__name__)
1399 line = self._line_buffer or self.shell.readline()
1400 if size < 0:
1401 size = len(line)
Serhiy Storchaka0b6b3352013-12-25 14:24:17 +02001402 eol = line.find('\n', 0, size)
1403 if eol >= 0:
1404 size = eol + 1
Serhiy Storchaka9abc8302013-01-25 15:30:35 +02001405 self._line_buffer = line[size:]
1406 return line[:size]
Martin v. Löwise2b56242012-07-25 10:56:22 +02001407
Roger Serwy53dc4f02013-04-11 19:13:21 -05001408 def close(self):
1409 self.shell.close()
1410
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001411
David Scherer7aced172000-08-15 01:13:23 +00001412usage_msg = """\
David Scherer7aced172000-08-15 01:13:23 +00001413
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001414USAGE: idle [-deins] [-t title] [file]*
1415 idle [-dns] [-t title] (-c cmd | -r file) [arg]*
1416 idle [-dns] [-t title] - [arg]*
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001417
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001418 -h print this help message and exit
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001419 -n run IDLE without a subprocess (see Help/IDLE Help for details)
David Scherer7aced172000-08-15 01:13:23 +00001420
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001421The following options will override the IDLE 'settings' configuration:
Kurt B. Kaiser96d88422001-07-17 04:59:01 +00001422
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001423 -e open an edit window
1424 -i open a shell window
1425
1426The following options imply -i and will open a shell:
1427
1428 -c cmd run the command in a shell, or
1429 -r file run script from file
1430
1431 -d enable the debugger
1432 -s run $IDLESTARTUP or $PYTHONSTARTUP before anything else
1433 -t title set title of shell window
1434
1435A default edit window will be bypassed when -c, -r, or - are used.
1436
1437[arg]* are passed to the command (-c) or script (-r) in sys.argv[1:].
1438
1439Examples:
1440
1441idle
1442 Open an edit window or shell depending on IDLE's configuration.
1443
1444idle foo.py foobar.py
1445 Edit the files, also open a shell if configured to start with shell.
1446
1447idle -est "Baz" foo.py
1448 Run $IDLESTARTUP or $PYTHONSTARTUP, edit foo.py, and open a shell
1449 window with the title "Baz".
1450
1451idle -c "import sys; print sys.argv" "foo"
1452 Open a shell window and run the command, passing "-c" in sys.argv[0]
1453 and "foo" in sys.argv[1].
1454
1455idle -d -s -r foo.py "Hello World"
1456 Open a shell window, run a startup script, enable the debugger, and
1457 run foo.py, passing "foo.py" in sys.argv[0] and "Hello World" in
1458 sys.argv[1].
1459
1460echo "import sys; print sys.argv" | idle - "foobar"
1461 Open a shell window, run the script piped in, passing '' in sys.argv[0]
1462 and "foobar" in sys.argv[1].
David Scherer7aced172000-08-15 01:13:23 +00001463"""
1464
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001465def main():
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001466 global flist, root, use_subprocess
David Scherer7aced172000-08-15 01:13:23 +00001467
Terry Jan Reedy8eab0082013-06-28 23:51:34 -04001468 capture_warnings(True)
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001469 use_subprocess = True
Roger Serwy34d0c662013-03-31 23:28:55 -05001470 enable_shell = False
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001471 enable_edit = False
1472 debug = False
1473 cmd = None
1474 script = None
1475 startup = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001476 try:
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001477 opts, args = getopt.getopt(sys.argv[1:], "c:deihnr:st:")
Terry Jan Reedy2b149862013-06-29 00:59:34 -04001478 except getopt.error as msg:
Terry Jan Reedybee003c2014-09-19 22:37:24 -04001479 print("Error: %s\n%s" % (msg, usage_msg), file=sys.stderr)
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001480 sys.exit(2)
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001481 for o, a in opts:
1482 if o == '-c':
1483 cmd = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001484 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001485 if o == '-d':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001486 debug = True
1487 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001488 if o == '-e':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001489 enable_edit = True
1490 if o == '-h':
1491 sys.stdout.write(usage_msg)
1492 sys.exit()
1493 if o == '-i':
1494 enable_shell = True
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001495 if o == '-n':
1496 use_subprocess = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001497 if o == '-r':
1498 script = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001499 if os.path.isfile(script):
1500 pass
1501 else:
Terry Jan Reedybee003c2014-09-19 22:37:24 -04001502 print("No script file: ", script, file=sys.stderr)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001503 sys.exit()
1504 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001505 if o == '-s':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001506 startup = True
1507 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001508 if o == '-t':
1509 PyShell.shell_title = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001510 enable_shell = True
1511 if args and args[0] == '-':
1512 cmd = sys.stdin.read()
1513 enable_shell = True
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001514 # process sys.argv and sys.path:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001515 for i in range(len(sys.path)):
1516 sys.path[i] = os.path.abspath(sys.path[i])
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001517 if args and args[0] == '-':
1518 sys.argv = [''] + args[1:]
1519 elif cmd:
1520 sys.argv = ['-c'] + args
1521 elif script:
1522 sys.argv = [script] + args
1523 elif args:
1524 enable_edit = True
1525 pathx = []
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001526 for filename in args:
1527 pathx.append(os.path.dirname(filename))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001528 for dir in pathx:
1529 dir = os.path.abspath(dir)
Florent Xiclunad630c042010-04-02 07:24:52 +00001530 if dir not in sys.path:
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001531 sys.path.insert(0, dir)
Kurt B. Kaiserff002b92002-12-21 21:39:11 +00001532 else:
1533 dir = os.getcwd()
1534 if not dir in sys.path:
1535 sys.path.insert(0, dir)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001536 # check the IDLE settings configuration (but command line overrides)
1537 edit_start = idleConf.GetOption('main', 'General',
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001538 'editor-on-startup', type='bool')
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001539 enable_edit = enable_edit or edit_start
Roger Serwy34d0c662013-03-31 23:28:55 -05001540 enable_shell = enable_shell or not enable_edit
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001541 # start editor and/or shell windows:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001542 root = Tk(className="Idle")
Ronald Oussoren19302d92006-06-11 14:33:36 +00001543
Terry Jan Reedy4ade2d22014-02-08 09:39:51 -05001544 # set application icon
1545 icondir = os.path.join(os.path.dirname(__file__), 'Icons')
1546 if system() == 'Windows':
1547 iconfile = os.path.join(icondir, 'idle.ico')
1548 root.wm_iconbitmap(default=iconfile)
1549 elif TkVersion >= 8.5:
1550 ext = '.png' if TkVersion >= 8.6 else '.gif'
1551 iconfiles = [os.path.join(icondir, 'idle_%d%s' % (size, ext))
1552 for size in (16, 32, 48)]
1553 icons = [PhotoImage(file=iconfile) for iconfile in iconfiles]
1554 root.tk.call('wm', 'iconphoto', str(root), "-default", *icons)
1555
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001556 fixwordbreaks(root)
1557 root.withdraw()
1558 flist = PyShellFileList(root)
Ronald Oussoren19302d92006-06-11 14:33:36 +00001559 macosxSupport.setupApp(root, flist)
1560
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001561 if enable_edit:
1562 if not (cmd or script):
Andrew Svetlov7c010ee2012-03-21 13:35:08 +02001563 for filename in args[:]:
1564 if flist.open(filename) is None:
1565 # filename is a directory actually, disconsider it
1566 args.remove(filename)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001567 if not args:
1568 flist.new()
Ned Deily278543d2013-12-10 16:21:58 -08001569
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001570 if enable_shell:
Ronald Oussoren19302d92006-06-11 14:33:36 +00001571 shell = flist.open_shell()
1572 if not shell:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001573 return # couldn't open shell
Ned Deily57847df2014-03-27 20:47:04 -07001574 if macosxSupport.isAquaTk() and flist.dict:
Ronald Oussoren19302d92006-06-11 14:33:36 +00001575 # On OSX: when the user has double-clicked on a file that causes
Tim Peters4f96f1f2006-06-11 19:42:51 +00001576 # IDLE to be launched the shell window will open just in front of
1577 # the file she wants to see. Lower the interpreter window when
Ronald Oussoren19302d92006-06-11 14:33:36 +00001578 # there are open files.
1579 shell.top.lower()
Ned Deily278543d2013-12-10 16:21:58 -08001580 else:
1581 shell = flist.pyshell
Ronald Oussoren19302d92006-06-11 14:33:36 +00001582
Ned Deily278543d2013-12-10 16:21:58 -08001583 # Handle remaining options. If any of these are set, enable_shell
1584 # was set also, so shell must be true to reach here.
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001585 if debug:
1586 shell.open_debugger()
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001587 if startup:
1588 filename = os.environ.get("IDLESTARTUP") or \
1589 os.environ.get("PYTHONSTARTUP")
1590 if filename and os.path.isfile(filename):
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001591 shell.interp.execfile(filename)
Ned Deily278543d2013-12-10 16:21:58 -08001592 if cmd or script:
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001593 shell.interp.runcommand("""if 1:
1594 import sys as _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001595 _sys.argv = %r
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001596 del _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001597 \n""" % (sys.argv,))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001598 if cmd:
1599 shell.interp.execsource(cmd)
1600 elif script:
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001601 shell.interp.prepend_syspath(script)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001602 shell.interp.execfile(script)
Ned Deily278543d2013-12-10 16:21:58 -08001603 elif shell:
1604 # If there is a shell window and no cmd or script in progress,
1605 # check for problematic OS X Tk versions and print a warning
1606 # message in the IDLE shell window; this is less intrusive
1607 # than always opening a separate window.
1608 tkversionwarning = macosxSupport.tkVersionWarning(root)
1609 if tkversionwarning:
1610 shell.interp.runcommand("print('%s')" % tkversionwarning)
Ned Deily2a6f4b32011-01-30 00:18:47 +00001611
Terry Jan Reedyeaa7e782012-05-26 20:33:32 -04001612 while flist.inversedict: # keep IDLE running while files are open.
1613 root.mainloop()
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001614 root.destroy()
Terry Jan Reedy8eab0082013-06-28 23:51:34 -04001615 capture_warnings(False)
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001616
David Scherer7aced172000-08-15 01:13:23 +00001617if __name__ == "__main__":
Kurt B. Kaiser9e8b8282003-06-15 17:38:45 +00001618 sys.modules['PyShell'] = sys.modules['__main__']
David Scherer7aced172000-08-15 01:13:23 +00001619 main()
Terry Jan Reedy8eab0082013-06-28 23:51:34 -04001620
1621capture_warnings(False) # Make sure turned off; see issue 18081