blob: 427d3ce72c3a413e3a98a5a645afd1236ed2e92b [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"),
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000874 ("windows", "_Windows"),
875 ("help", "_Help"),
876 ]
David Scherer7aced172000-08-15 01:13:23 +0000877
Ned Deily57847df2014-03-27 20:47:04 -0700878 if sys.platform == "darwin":
Ronald Oussoren19302d92006-06-11 14:33:36 +0000879 menu_specs[-2] = ("windows", "_Window")
880
881
David Scherer7aced172000-08-15 01:13:23 +0000882 # New classes
Florent Xiclunad630c042010-04-02 07:24:52 +0000883 from idlelib.IdleHistory import History
David Scherer7aced172000-08-15 01:13:23 +0000884
885 def __init__(self, flist=None):
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000886 if use_subprocess:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000887 ms = self.menu_specs
888 if ms[2][0] != "shell":
Kurt B. Kaiser7ae35482006-08-16 21:45:59 +0000889 ms.insert(2, ("shell", "She_ll"))
David Scherer7aced172000-08-15 01:13:23 +0000890 self.interp = ModifiedInterpreter(self)
891 if flist is None:
892 root = Tk()
893 fixwordbreaks(root)
894 root.withdraw()
895 flist = PyShellFileList(root)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000896 #
David Scherer7aced172000-08-15 01:13:23 +0000897 OutputWindow.__init__(self, flist, None, None)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000898 #
Kurt B. Kaiser6af44982005-01-19 00:22:59 +0000899## self.config(usetabs=1, indentwidth=8, context_use_ps1=1)
900 self.usetabs = True
901 # indentwidth must be 8 when using tabs. See note in EditorWindow:
902 self.indentwidth = 8
903 self.context_use_ps1 = True
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000904 #
David Scherer7aced172000-08-15 01:13:23 +0000905 text = self.text
906 text.configure(wrap="char")
907 text.bind("<<newline-and-indent>>", self.enter_callback)
908 text.bind("<<plain-newline-and-indent>>", self.linefeed_callback)
909 text.bind("<<interrupt-execution>>", self.cancel_callback)
David Scherer7aced172000-08-15 01:13:23 +0000910 text.bind("<<end-of-file>>", self.eof_callback)
911 text.bind("<<open-stack-viewer>>", self.open_stack_viewer)
Kurt B. Kaiser57bfe5d2003-05-10 00:09:52 +0000912 text.bind("<<toggle-debugger>>", self.toggle_debugger)
David Scherer7aced172000-08-15 01:13:23 +0000913 text.bind("<<toggle-jit-stack-viewer>>", self.toggle_jit_stack_viewer)
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000914 if use_subprocess:
915 text.bind("<<view-restart>>", self.view_restart_mark)
916 text.bind("<<restart-shell>>", self.restart_shell)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000917 #
David Scherer7aced172000-08-15 01:13:23 +0000918 self.save_stdout = sys.stdout
919 self.save_stderr = sys.stderr
920 self.save_stdin = sys.stdin
Florent Xiclunad630c042010-04-02 07:24:52 +0000921 from idlelib import IOBinding
Serhiy Storchaka9abc8302013-01-25 15:30:35 +0200922 self.stdin = PseudoInputFile(self, "stdin", IOBinding.encoding)
923 self.stdout = PseudoOutputFile(self, "stdout", IOBinding.encoding)
924 self.stderr = PseudoOutputFile(self, "stderr", IOBinding.encoding)
925 self.console = PseudoOutputFile(self, "console", IOBinding.encoding)
Chui Tey5d2af632002-05-26 13:36:41 +0000926 if not use_subprocess:
927 sys.stdout = self.stdout
928 sys.stderr = self.stderr
Martin v. Löwise2b56242012-07-25 10:56:22 +0200929 sys.stdin = self.stdin
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000930 #
David Scherer7aced172000-08-15 01:13:23 +0000931 self.history = self.History(self.text)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000932 #
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000933 self.pollinterval = 50 # millisec
Chui Tey5d2af632002-05-26 13:36:41 +0000934
Kurt B. Kaiser4d5bc602004-06-06 01:29:22 +0000935 def get_standard_extension_names(self):
936 return idleConf.GetExtensions(shell_only=True)
937
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000938 reading = False
939 executing = False
940 canceled = False
941 endoffile = False
942 closing = False
Roger Serwyad8cad32013-04-03 00:42:24 -0500943 _stop_readline_flag = False
David Scherer7aced172000-08-15 01:13:23 +0000944
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +0000945 def set_warning_stream(self, stream):
Skip Montanarod9161422004-07-06 21:53:27 +0000946 global warning_stream
947 warning_stream = stream
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +0000948
949 def get_warning_stream(self):
950 return warning_stream
951
David Scherer7aced172000-08-15 01:13:23 +0000952 def toggle_debugger(self, event=None):
953 if self.executing:
954 tkMessageBox.showerror("Don't debug now",
955 "You can only toggle the debugger when idle",
956 master=self.text)
957 self.set_debugger_indicator()
958 return "break"
959 else:
960 db = self.interp.getdebugger()
961 if db:
962 self.close_debugger()
963 else:
964 self.open_debugger()
965
966 def set_debugger_indicator(self):
967 db = self.interp.getdebugger()
968 self.setvar("<<toggle-debugger>>", not not db)
969
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000970 def toggle_jit_stack_viewer(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +0000971 pass # All we need is the variable
972
973 def close_debugger(self):
974 db = self.interp.getdebugger()
975 if db:
976 self.interp.setdebugger(None)
977 db.close()
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000978 if self.interp.rpcclt:
979 RemoteDebugger.close_remote_debugger(self.interp.rpcclt)
David Scherer7aced172000-08-15 01:13:23 +0000980 self.resetoutput()
981 self.console.write("[DEBUG OFF]\n")
982 sys.ps1 = ">>> "
983 self.showprompt()
984 self.set_debugger_indicator()
985
986 def open_debugger(self):
Chui Tey5d2af632002-05-26 13:36:41 +0000987 if self.interp.rpcclt:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000988 dbg_gui = RemoteDebugger.start_remote_debugger(self.interp.rpcclt,
989 self)
990 else:
991 dbg_gui = Debugger.Debugger(self)
992 self.interp.setdebugger(dbg_gui)
993 dbg_gui.load_breakpoints()
Chui Tey5d2af632002-05-26 13:36:41 +0000994 sys.ps1 = "[DEBUG ON]\n>>> "
995 self.showprompt()
996 self.set_debugger_indicator()
997
David Scherer7aced172000-08-15 01:13:23 +0000998 def beginexecuting(self):
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000999 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +00001000 self.resetoutput()
1001 self.executing = 1
David Scherer7aced172000-08-15 01:13:23 +00001002
1003 def endexecuting(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +00001004 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +00001005 self.executing = 0
1006 self.canceled = 0
Chui Tey5d2af632002-05-26 13:36:41 +00001007 self.showprompt()
David Scherer7aced172000-08-15 01:13:23 +00001008
1009 def close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +00001010 "Extend EditorWindow.close()"
David Scherer7aced172000-08-15 01:13:23 +00001011 if self.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001012 response = tkMessageBox.askokcancel(
David Scherer7aced172000-08-15 01:13:23 +00001013 "Kill?",
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001014 "The program is still running!\n Do you want to kill it?",
David Scherer7aced172000-08-15 01:13:23 +00001015 default="ok",
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001016 parent=self.text)
Benjamin Peterson5b63acd2008-03-29 15:24:25 +00001017 if response is False:
David Scherer7aced172000-08-15 01:13:23 +00001018 return "cancel"
Roger Serwyad8cad32013-04-03 00:42:24 -05001019 self.stop_readline()
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001020 self.canceled = True
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +00001021 self.closing = True
Kurt B. Kaiser88957d82003-05-19 23:11:51 +00001022 return EditorWindow.close(self)
David Scherer7aced172000-08-15 01:13:23 +00001023
1024 def _close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +00001025 "Extend EditorWindow._close(), shut down debugger and execution server"
David Scherer7aced172000-08-15 01:13:23 +00001026 self.close_debugger()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001027 if use_subprocess:
1028 self.interp.kill_subprocess()
David Scherer7aced172000-08-15 01:13:23 +00001029 # Restore std streams
1030 sys.stdout = self.save_stdout
1031 sys.stderr = self.save_stderr
1032 sys.stdin = self.save_stdin
1033 # Break cycles
1034 self.interp = None
1035 self.console = None
David Scherer7aced172000-08-15 01:13:23 +00001036 self.flist.pyshell = None
1037 self.history = None
Kurt B. Kaiser83118c62002-06-24 17:03:37 +00001038 EditorWindow._close(self)
David Scherer7aced172000-08-15 01:13:23 +00001039
1040 def ispythonsource(self, filename):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +00001041 "Override EditorWindow method: never remove the colorizer"
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001042 return True
David Scherer7aced172000-08-15 01:13:23 +00001043
1044 def short_title(self):
1045 return self.shell_title
1046
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +00001047 COPYRIGHT = \
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001048 'Type "copyright", "credits" or "license()" for more information.'
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +00001049
David Scherer7aced172000-08-15 01:13:23 +00001050 def begin(self):
1051 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001052 if use_subprocess:
1053 nosub = ''
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001054 client = self.interp.start_subprocess()
1055 if not client:
1056 self.close()
Kurt B. Kaiser76637292004-01-21 22:10:01 +00001057 return False
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001058 else:
1059 nosub = "==== No Subprocess ===="
Raymond Hettingerbf3f69e2009-01-26 23:29:09 +00001060 self.write("Python %s on %s\n%s\n%s" %
1061 (sys.version, sys.platform, self.COPYRIGHT, nosub))
David Scherer7aced172000-08-15 01:13:23 +00001062 self.showprompt()
Georg Brandl6634bf22008-05-20 07:13:37 +00001063 import Tkinter
1064 Tkinter._default_root = None # 03Jan04 KBK What's this?
Kurt B. Kaiser76637292004-01-21 22:10:01 +00001065 return True
David Scherer7aced172000-08-15 01:13:23 +00001066
Roger Serwyad8cad32013-04-03 00:42:24 -05001067 def stop_readline(self):
1068 if not self.reading: # no nested mainloop to exit.
1069 return
1070 self._stop_readline_flag = True
1071 self.top.quit()
1072
David Scherer7aced172000-08-15 01:13:23 +00001073 def readline(self):
1074 save = self.reading
1075 try:
1076 self.reading = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001077 self.top.mainloop() # nested mainloop()
David Scherer7aced172000-08-15 01:13:23 +00001078 finally:
1079 self.reading = save
Roger Serwyad8cad32013-04-03 00:42:24 -05001080 if self._stop_readline_flag:
1081 self._stop_readline_flag = False
1082 return ""
David Scherer7aced172000-08-15 01:13:23 +00001083 line = self.text.get("iomark", "end-1c")
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001084 if len(line) == 0: # may be EOF if we quit our mainloop with Ctrl-C
1085 line = "\n"
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001086 if isinstance(line, unicode):
Florent Xiclunad630c042010-04-02 07:24:52 +00001087 from idlelib import IOBinding
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001088 try:
1089 line = line.encode(IOBinding.encoding)
1090 except UnicodeError:
1091 pass
David Scherer7aced172000-08-15 01:13:23 +00001092 self.resetoutput()
1093 if self.canceled:
1094 self.canceled = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001095 if not use_subprocess:
1096 raise KeyboardInterrupt
David Scherer7aced172000-08-15 01:13:23 +00001097 if self.endoffile:
1098 self.endoffile = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001099 line = ""
David Scherer7aced172000-08-15 01:13:23 +00001100 return line
1101
1102 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001103 return True
David Scherer7aced172000-08-15 01:13:23 +00001104
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001105 def cancel_callback(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +00001106 try:
1107 if self.text.compare("sel.first", "!=", "sel.last"):
1108 return # Active selection -- always use default binding
1109 except:
1110 pass
1111 if not (self.executing or self.reading):
1112 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001113 self.interp.write("KeyboardInterrupt\n")
David Scherer7aced172000-08-15 01:13:23 +00001114 self.showprompt()
1115 return "break"
1116 self.endoffile = 0
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001117 self.canceled = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001118 if (self.executing and self.interp.rpcclt):
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +00001119 if self.interp.getdebugger():
1120 self.interp.restart_subprocess()
1121 else:
1122 self.interp.interrupt_subprocess()
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001123 if self.reading:
1124 self.top.quit() # exit the nested mainloop() in readline()
David Scherer7aced172000-08-15 01:13:23 +00001125 return "break"
1126
1127 def eof_callback(self, event):
1128 if self.executing and not self.reading:
1129 return # Let the default binding (delete next char) take over
1130 if not (self.text.compare("iomark", "==", "insert") and
1131 self.text.compare("insert", "==", "end-1c")):
1132 return # Let the default binding (delete next char) take over
1133 if not self.executing:
David Scherer7aced172000-08-15 01:13:23 +00001134 self.resetoutput()
1135 self.close()
1136 else:
1137 self.canceled = 0
1138 self.endoffile = 1
1139 self.top.quit()
1140 return "break"
1141
David Scherer7aced172000-08-15 01:13:23 +00001142 def linefeed_callback(self, event):
1143 # Insert a linefeed without entering anything (still autoindented)
1144 if self.reading:
1145 self.text.insert("insert", "\n")
1146 self.text.see("insert")
1147 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001148 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001149 return "break"
1150
1151 def enter_callback(self, event):
1152 if self.executing and not self.reading:
1153 return # Let the default binding (insert '\n') take over
1154 # If some text is selected, recall the selection
1155 # (but only if this before the I/O mark)
1156 try:
1157 sel = self.text.get("sel.first", "sel.last")
1158 if sel:
1159 if self.text.compare("sel.last", "<=", "iomark"):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001160 self.recall(sel, event)
David Scherer7aced172000-08-15 01:13:23 +00001161 return "break"
1162 except:
1163 pass
1164 # If we're strictly before the line containing iomark, recall
1165 # the current line, less a leading prompt, less leading or
1166 # trailing whitespace
1167 if self.text.compare("insert", "<", "iomark linestart"):
1168 # Check if there's a relevant stdin range -- if so, use it
1169 prev = self.text.tag_prevrange("stdin", "insert")
1170 if prev and self.text.compare("insert", "<", prev[1]):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001171 self.recall(self.text.get(prev[0], prev[1]), event)
David Scherer7aced172000-08-15 01:13:23 +00001172 return "break"
1173 next = self.text.tag_nextrange("stdin", "insert")
1174 if next and self.text.compare("insert lineend", ">=", next[0]):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001175 self.recall(self.text.get(next[0], next[1]), event)
David Scherer7aced172000-08-15 01:13:23 +00001176 return "break"
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001177 # No stdin mark -- just get the current line, less any prompt
Kurt B. Kaiserb1754452005-11-18 22:05:48 +00001178 indices = self.text.tag_nextrange("console", "insert linestart")
1179 if indices and \
1180 self.text.compare(indices[0], "<=", "insert linestart"):
1181 self.recall(self.text.get(indices[1], "insert lineend"), event)
1182 else:
1183 self.recall(self.text.get("insert linestart", "insert lineend"), event)
David Scherer7aced172000-08-15 01:13:23 +00001184 return "break"
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001185 # If we're between the beginning of the line and the iomark, i.e.
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001186 # in the prompt area, move to the end of the prompt
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001187 if self.text.compare("insert", "<", "iomark"):
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001188 self.text.mark_set("insert", "iomark")
David Scherer7aced172000-08-15 01:13:23 +00001189 # If we're in the current input and there's only whitespace
1190 # beyond the cursor, erase that whitespace first
1191 s = self.text.get("insert", "end-1c")
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001192 if s and not s.strip():
David Scherer7aced172000-08-15 01:13:23 +00001193 self.text.delete("insert", "end-1c")
1194 # If we're in the current input before its last line,
1195 # insert a newline right at the insert point
1196 if self.text.compare("insert", "<", "end-1c linestart"):
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001197 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001198 return "break"
1199 # We're in the last line; append a newline and submit it
1200 self.text.mark_set("insert", "end-1c")
1201 if self.reading:
1202 self.text.insert("insert", "\n")
1203 self.text.see("insert")
1204 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001205 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001206 self.text.tag_add("stdin", "iomark", "end-1c")
1207 self.text.update_idletasks()
1208 if self.reading:
1209 self.top.quit() # Break out of recursive mainloop() in raw_input()
1210 else:
1211 self.runit()
1212 return "break"
1213
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001214 def recall(self, s, event):
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001215 # remove leading and trailing empty or whitespace lines
1216 s = re.sub(r'^\s*\n', '' , s)
1217 s = re.sub(r'\n\s*$', '', s)
1218 lines = s.split('\n')
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001219 self.text.undo_block_start()
1220 try:
1221 self.text.tag_remove("sel", "1.0", "end")
1222 self.text.mark_set("insert", "end-1c")
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001223 prefix = self.text.get("insert linestart", "insert")
1224 if prefix.rstrip().endswith(':'):
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001225 self.newline_and_indent_event(event)
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001226 prefix = self.text.get("insert linestart", "insert")
1227 self.text.insert("insert", lines[0].strip())
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001228 if len(lines) > 1:
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001229 orig_base_indent = re.search(r'^([ \t]*)', lines[0]).group(0)
1230 new_base_indent = re.search(r'^([ \t]*)', prefix).group(0)
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001231 for line in lines[1:]:
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001232 if line.startswith(orig_base_indent):
1233 # replace orig base indentation with new indentation
1234 line = new_base_indent + line[len(orig_base_indent):]
1235 self.text.insert('insert', '\n'+line.rstrip())
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001236 finally:
1237 self.text.see("insert")
1238 self.text.undo_block_stop()
David Scherer7aced172000-08-15 01:13:23 +00001239
1240 def runit(self):
1241 line = self.text.get("iomark", "end-1c")
1242 # Strip off last newline and surrounding whitespace.
1243 # (To allow you to hit return twice to end a statement.)
1244 i = len(line)
1245 while i > 0 and line[i-1] in " \t":
1246 i = i-1
1247 if i > 0 and line[i-1] == "\n":
1248 i = i-1
1249 while i > 0 and line[i-1] in " \t":
1250 i = i-1
1251 line = line[:i]
1252 more = self.interp.runsource(line)
David Scherer7aced172000-08-15 01:13:23 +00001253
David Scherer7aced172000-08-15 01:13:23 +00001254 def open_stack_viewer(self, event=None):
Chui Tey5d2af632002-05-26 13:36:41 +00001255 if self.interp.rpcclt:
1256 return self.interp.remote_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +00001257 try:
1258 sys.last_traceback
1259 except:
1260 tkMessageBox.showerror("No stack trace",
1261 "There is no stack trace yet.\n"
1262 "(sys.last_traceback is not defined)",
1263 master=self.text)
1264 return
Florent Xiclunad630c042010-04-02 07:24:52 +00001265 from idlelib.StackViewer import StackBrowser
David Scherer7aced172000-08-15 01:13:23 +00001266 sv = StackBrowser(self.root, self.flist)
1267
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001268 def view_restart_mark(self, event=None):
1269 self.text.see("iomark")
1270 self.text.see("restart")
1271
1272 def restart_shell(self, event=None):
Terry Jan Reedyb98000a2012-01-31 02:09:25 -05001273 "Callback for Run/Restart Shell Cntl-F6"
1274 self.interp.restart_subprocess(with_cwd=True)
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001275
David Scherer7aced172000-08-15 01:13:23 +00001276 def showprompt(self):
1277 self.resetoutput()
1278 try:
1279 s = str(sys.ps1)
1280 except:
1281 s = ""
1282 self.console.write(s)
1283 self.text.mark_set("insert", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001284 self.set_line_and_column()
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +00001285 self.io.reset_undo()
David Scherer7aced172000-08-15 01:13:23 +00001286
1287 def resetoutput(self):
1288 source = self.text.get("iomark", "end-1c")
1289 if self.history:
Terry Jan Reedyb638a382013-08-13 19:51:04 -04001290 self.history.store(source)
David Scherer7aced172000-08-15 01:13:23 +00001291 if self.text.get("end-2c") != "\n":
1292 self.text.insert("end-1c", "\n")
1293 self.text.mark_set("iomark", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001294 self.set_line_and_column()
David Scherer7aced172000-08-15 01:13:23 +00001295 sys.stdout.softspace = 0
1296
1297 def write(self, s, tags=()):
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001298 try:
1299 self.text.mark_gravity("iomark", "right")
1300 OutputWindow.write(self, s, tags, "iomark")
1301 self.text.mark_gravity("iomark", "left")
1302 except:
1303 pass
David Scherer7aced172000-08-15 01:13:23 +00001304 if self.canceled:
1305 self.canceled = 0
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001306 if not use_subprocess:
1307 raise KeyboardInterrupt
David Scherer7aced172000-08-15 01:13:23 +00001308
Andrew Svetlov5018db72012-11-01 22:39:14 +02001309 def rmenu_check_cut(self):
1310 try:
1311 if self.text.compare('sel.first', '<', 'iomark'):
1312 return 'disabled'
1313 except TclError: # no selection, so the index 'sel.first' doesn't exist
1314 return 'disabled'
1315 return super(PyShell, self).rmenu_check_cut()
1316
1317 def rmenu_check_paste(self):
1318 if self.text.compare('insert', '<', 'iomark'):
1319 return 'disabled'
1320 return super(PyShell, self).rmenu_check_paste()
1321
Serhiy Storchaka9abc8302013-01-25 15:30:35 +02001322class PseudoFile(io.TextIOBase):
David Scherer7aced172000-08-15 01:13:23 +00001323
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001324 def __init__(self, shell, tags, encoding=None):
David Scherer7aced172000-08-15 01:13:23 +00001325 self.shell = shell
1326 self.tags = tags
Chui Tey5d2af632002-05-26 13:36:41 +00001327 self.softspace = 0
Serhiy Storchaka9abc8302013-01-25 15:30:35 +02001328 self._encoding = encoding
David Scherer7aced172000-08-15 01:13:23 +00001329
Serhiy Storchaka9abc8302013-01-25 15:30:35 +02001330 @property
1331 def encoding(self):
1332 return self._encoding
David Scherer7aced172000-08-15 01:13:23 +00001333
Serhiy Storchaka9abc8302013-01-25 15:30:35 +02001334 @property
1335 def name(self):
1336 return '<%s>' % self.tags
David Scherer7aced172000-08-15 01:13:23 +00001337
1338 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001339 return True
David Scherer7aced172000-08-15 01:13:23 +00001340
Serhiy Storchaka9abc8302013-01-25 15:30:35 +02001341
1342class PseudoOutputFile(PseudoFile):
1343
1344 def writable(self):
1345 return True
Martin v. Löwise2b56242012-07-25 10:56:22 +02001346
1347 def write(self, s):
Serhiy Storchaka9abc8302013-01-25 15:30:35 +02001348 if self.closed:
1349 raise ValueError("write to closed file")
Serhiy Storchaka7057f3f2013-12-10 10:04:41 +02001350 if type(s) not in (unicode, str, bytearray):
1351 # See issue #19481
1352 if isinstance(s, unicode):
1353 s = unicode.__getslice__(s, None, None)
1354 elif isinstance(s, str):
1355 s = str.__str__(s)
1356 elif isinstance(s, bytearray):
1357 s = bytearray.__str__(s)
1358 else:
1359 raise TypeError('must be string, not ' + type(s).__name__)
Serhiy Storchaka9abc8302013-01-25 15:30:35 +02001360 return self.shell.write(s, self.tags)
1361
1362
1363class PseudoInputFile(PseudoFile):
1364
1365 def __init__(self, shell, tags, encoding=None):
1366 PseudoFile.__init__(self, shell, tags, encoding)
1367 self._line_buffer = ''
1368
1369 def readable(self):
1370 return True
1371
1372 def read(self, size=-1):
1373 if self.closed:
1374 raise ValueError("read from closed file")
1375 if size is None:
1376 size = -1
1377 elif not isinstance(size, int):
1378 raise TypeError('must be int, not ' + type(size).__name__)
1379 result = self._line_buffer
1380 self._line_buffer = ''
1381 if size < 0:
1382 while True:
1383 line = self.shell.readline()
1384 if not line: break
1385 result += line
1386 else:
1387 while len(result) < size:
1388 line = self.shell.readline()
1389 if not line: break
1390 result += line
1391 self._line_buffer = result[size:]
1392 result = result[:size]
1393 return result
1394
1395 def readline(self, size=-1):
1396 if self.closed:
1397 raise ValueError("read from closed file")
1398 if size is None:
1399 size = -1
1400 elif not isinstance(size, int):
1401 raise TypeError('must be int, not ' + type(size).__name__)
1402 line = self._line_buffer or self.shell.readline()
1403 if size < 0:
1404 size = len(line)
Serhiy Storchaka0b6b3352013-12-25 14:24:17 +02001405 eol = line.find('\n', 0, size)
1406 if eol >= 0:
1407 size = eol + 1
Serhiy Storchaka9abc8302013-01-25 15:30:35 +02001408 self._line_buffer = line[size:]
1409 return line[:size]
Martin v. Löwise2b56242012-07-25 10:56:22 +02001410
Roger Serwy53dc4f02013-04-11 19:13:21 -05001411 def close(self):
1412 self.shell.close()
1413
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001414
David Scherer7aced172000-08-15 01:13:23 +00001415usage_msg = """\
David Scherer7aced172000-08-15 01:13:23 +00001416
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001417USAGE: idle [-deins] [-t title] [file]*
1418 idle [-dns] [-t title] (-c cmd | -r file) [arg]*
1419 idle [-dns] [-t title] - [arg]*
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001420
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001421 -h print this help message and exit
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001422 -n run IDLE without a subprocess (see Help/IDLE Help for details)
David Scherer7aced172000-08-15 01:13:23 +00001423
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001424The following options will override the IDLE 'settings' configuration:
Kurt B. Kaiser96d88422001-07-17 04:59:01 +00001425
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001426 -e open an edit window
1427 -i open a shell window
1428
1429The following options imply -i and will open a shell:
1430
1431 -c cmd run the command in a shell, or
1432 -r file run script from file
1433
1434 -d enable the debugger
1435 -s run $IDLESTARTUP or $PYTHONSTARTUP before anything else
1436 -t title set title of shell window
1437
1438A default edit window will be bypassed when -c, -r, or - are used.
1439
1440[arg]* are passed to the command (-c) or script (-r) in sys.argv[1:].
1441
1442Examples:
1443
1444idle
1445 Open an edit window or shell depending on IDLE's configuration.
1446
1447idle foo.py foobar.py
1448 Edit the files, also open a shell if configured to start with shell.
1449
1450idle -est "Baz" foo.py
1451 Run $IDLESTARTUP or $PYTHONSTARTUP, edit foo.py, and open a shell
1452 window with the title "Baz".
1453
1454idle -c "import sys; print sys.argv" "foo"
1455 Open a shell window and run the command, passing "-c" in sys.argv[0]
1456 and "foo" in sys.argv[1].
1457
1458idle -d -s -r foo.py "Hello World"
1459 Open a shell window, run a startup script, enable the debugger, and
1460 run foo.py, passing "foo.py" in sys.argv[0] and "Hello World" in
1461 sys.argv[1].
1462
1463echo "import sys; print sys.argv" | idle - "foobar"
1464 Open a shell window, run the script piped in, passing '' in sys.argv[0]
1465 and "foobar" in sys.argv[1].
David Scherer7aced172000-08-15 01:13:23 +00001466"""
1467
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001468def main():
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001469 global flist, root, use_subprocess
David Scherer7aced172000-08-15 01:13:23 +00001470
Terry Jan Reedy8eab0082013-06-28 23:51:34 -04001471 capture_warnings(True)
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001472 use_subprocess = True
Roger Serwy34d0c662013-03-31 23:28:55 -05001473 enable_shell = False
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001474 enable_edit = False
1475 debug = False
1476 cmd = None
1477 script = None
1478 startup = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001479 try:
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001480 opts, args = getopt.getopt(sys.argv[1:], "c:deihnr:st:")
Terry Jan Reedy2b149862013-06-29 00:59:34 -04001481 except getopt.error as msg:
Terry Jan Reedybee003c2014-09-19 22:37:24 -04001482 print("Error: %s\n%s" % (msg, usage_msg), file=sys.stderr)
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001483 sys.exit(2)
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001484 for o, a in opts:
1485 if o == '-c':
1486 cmd = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001487 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001488 if o == '-d':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001489 debug = True
1490 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001491 if o == '-e':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001492 enable_edit = True
1493 if o == '-h':
1494 sys.stdout.write(usage_msg)
1495 sys.exit()
1496 if o == '-i':
1497 enable_shell = True
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001498 if o == '-n':
1499 use_subprocess = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001500 if o == '-r':
1501 script = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001502 if os.path.isfile(script):
1503 pass
1504 else:
Terry Jan Reedybee003c2014-09-19 22:37:24 -04001505 print("No script file: ", script, file=sys.stderr)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001506 sys.exit()
1507 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001508 if o == '-s':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001509 startup = True
1510 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001511 if o == '-t':
1512 PyShell.shell_title = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001513 enable_shell = True
1514 if args and args[0] == '-':
1515 cmd = sys.stdin.read()
1516 enable_shell = True
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001517 # process sys.argv and sys.path:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001518 for i in range(len(sys.path)):
1519 sys.path[i] = os.path.abspath(sys.path[i])
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001520 if args and args[0] == '-':
1521 sys.argv = [''] + args[1:]
1522 elif cmd:
1523 sys.argv = ['-c'] + args
1524 elif script:
1525 sys.argv = [script] + args
1526 elif args:
1527 enable_edit = True
1528 pathx = []
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001529 for filename in args:
1530 pathx.append(os.path.dirname(filename))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001531 for dir in pathx:
1532 dir = os.path.abspath(dir)
Florent Xiclunad630c042010-04-02 07:24:52 +00001533 if dir not in sys.path:
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001534 sys.path.insert(0, dir)
Kurt B. Kaiserff002b92002-12-21 21:39:11 +00001535 else:
1536 dir = os.getcwd()
1537 if not dir in sys.path:
1538 sys.path.insert(0, dir)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001539 # check the IDLE settings configuration (but command line overrides)
1540 edit_start = idleConf.GetOption('main', 'General',
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001541 'editor-on-startup', type='bool')
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001542 enable_edit = enable_edit or edit_start
Roger Serwy34d0c662013-03-31 23:28:55 -05001543 enable_shell = enable_shell or not enable_edit
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001544 # start editor and/or shell windows:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001545 root = Tk(className="Idle")
Ronald Oussoren19302d92006-06-11 14:33:36 +00001546
Terry Jan Reedy4ade2d22014-02-08 09:39:51 -05001547 # set application icon
1548 icondir = os.path.join(os.path.dirname(__file__), 'Icons')
1549 if system() == 'Windows':
1550 iconfile = os.path.join(icondir, 'idle.ico')
1551 root.wm_iconbitmap(default=iconfile)
1552 elif TkVersion >= 8.5:
1553 ext = '.png' if TkVersion >= 8.6 else '.gif'
1554 iconfiles = [os.path.join(icondir, 'idle_%d%s' % (size, ext))
1555 for size in (16, 32, 48)]
1556 icons = [PhotoImage(file=iconfile) for iconfile in iconfiles]
1557 root.tk.call('wm', 'iconphoto', str(root), "-default", *icons)
1558
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001559 fixwordbreaks(root)
1560 root.withdraw()
1561 flist = PyShellFileList(root)
Ronald Oussoren19302d92006-06-11 14:33:36 +00001562 macosxSupport.setupApp(root, flist)
1563
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001564 if enable_edit:
1565 if not (cmd or script):
Andrew Svetlov7c010ee2012-03-21 13:35:08 +02001566 for filename in args[:]:
1567 if flist.open(filename) is None:
1568 # filename is a directory actually, disconsider it
1569 args.remove(filename)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001570 if not args:
1571 flist.new()
Ned Deily278543d2013-12-10 16:21:58 -08001572
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001573 if enable_shell:
Ronald Oussoren19302d92006-06-11 14:33:36 +00001574 shell = flist.open_shell()
1575 if not shell:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001576 return # couldn't open shell
Ned Deily57847df2014-03-27 20:47:04 -07001577 if macosxSupport.isAquaTk() and flist.dict:
Ronald Oussoren19302d92006-06-11 14:33:36 +00001578 # On OSX: when the user has double-clicked on a file that causes
Tim Peters4f96f1f2006-06-11 19:42:51 +00001579 # IDLE to be launched the shell window will open just in front of
1580 # the file she wants to see. Lower the interpreter window when
Ronald Oussoren19302d92006-06-11 14:33:36 +00001581 # there are open files.
1582 shell.top.lower()
Ned Deily278543d2013-12-10 16:21:58 -08001583 else:
1584 shell = flist.pyshell
Ronald Oussoren19302d92006-06-11 14:33:36 +00001585
Ned Deily278543d2013-12-10 16:21:58 -08001586 # Handle remaining options. If any of these are set, enable_shell
1587 # was set also, so shell must be true to reach here.
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001588 if debug:
1589 shell.open_debugger()
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001590 if startup:
1591 filename = os.environ.get("IDLESTARTUP") or \
1592 os.environ.get("PYTHONSTARTUP")
1593 if filename and os.path.isfile(filename):
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001594 shell.interp.execfile(filename)
Ned Deily278543d2013-12-10 16:21:58 -08001595 if cmd or script:
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001596 shell.interp.runcommand("""if 1:
1597 import sys as _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001598 _sys.argv = %r
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001599 del _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001600 \n""" % (sys.argv,))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001601 if cmd:
1602 shell.interp.execsource(cmd)
1603 elif script:
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001604 shell.interp.prepend_syspath(script)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001605 shell.interp.execfile(script)
Ned Deily278543d2013-12-10 16:21:58 -08001606 elif shell:
1607 # If there is a shell window and no cmd or script in progress,
1608 # check for problematic OS X Tk versions and print a warning
1609 # message in the IDLE shell window; this is less intrusive
1610 # than always opening a separate window.
1611 tkversionwarning = macosxSupport.tkVersionWarning(root)
1612 if tkversionwarning:
1613 shell.interp.runcommand("print('%s')" % tkversionwarning)
Ned Deily2a6f4b32011-01-30 00:18:47 +00001614
Terry Jan Reedyeaa7e782012-05-26 20:33:32 -04001615 while flist.inversedict: # keep IDLE running while files are open.
1616 root.mainloop()
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001617 root.destroy()
Terry Jan Reedy8eab0082013-06-28 23:51:34 -04001618 capture_warnings(False)
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001619
David Scherer7aced172000-08-15 01:13:23 +00001620if __name__ == "__main__":
Kurt B. Kaiser9e8b8282003-06-15 17:38:45 +00001621 sys.modules['PyShell'] = sys.modules['__main__']
David Scherer7aced172000-08-15 01:13:23 +00001622 main()
Terry Jan Reedy8eab0082013-06-28 23:51:34 -04001623
1624capture_warnings(False) # Make sure turned off; see issue 18081