blob: dc3cfe6120b6822e971bbf11c4deb9f6dc971659 [file] [log] [blame]
David Scherer7aced172000-08-15 01:13:23 +00001#! /usr/bin/env python
2
David Scherer7aced172000-08-15 01:13:23 +00003import os
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +00004import os.path
David Scherer7aced172000-08-15 01:13:23 +00005import sys
6import string
7import getopt
8import re
Chui Tey5d2af632002-05-26 13:36:41 +00009import socket
10import time
Kurt B. Kaiser003091c2003-02-17 18:57:16 +000011import threading
Chui Tey5d2af632002-05-26 13:36:41 +000012import traceback
Kurt B. Kaiser62833982002-09-18 17:07:05 +000013import types
Martin v. Löwise2b56242012-07-25 10:56:22 +020014import io
David Scherer7aced172000-08-15 01:13:23 +000015
16import linecache
17from code import InteractiveInterpreter
Terry Jan Reedyd676a3a2013-03-30 18:50:43 -040018from platform import python_version
David Scherer7aced172000-08-15 01:13:23 +000019
Kurt B. Kaiser2303b1c2003-11-24 05:26:16 +000020try:
Georg Brandl6634bf22008-05-20 07:13:37 +000021 from Tkinter import *
Kurt B. Kaiser2303b1c2003-11-24 05:26:16 +000022except ImportError:
Georg Brandl6634bf22008-05-20 07:13:37 +000023 print>>sys.__stderr__, "** IDLE can't import Tkinter. " \
Kurt B. Kaiser2303b1c2003-11-24 05:26:16 +000024 "Your Python may not be configured for Tk. **"
25 sys.exit(1)
Georg Brandl6634bf22008-05-20 07:13:37 +000026import tkMessageBox
David Scherer7aced172000-08-15 01:13:23 +000027
Florent Xiclunad630c042010-04-02 07:24:52 +000028from idlelib.EditorWindow import EditorWindow, fixwordbreaks
29from idlelib.FileList import FileList
30from idlelib.ColorDelegator import ColorDelegator
31from idlelib.UndoDelegator import UndoDelegator
32from idlelib.OutputWindow import OutputWindow
33from idlelib.configHandler import idleConf
34from idlelib import idlever
35from idlelib import rpc
36from idlelib import Debugger
37from idlelib import RemoteDebugger
38from idlelib import macosxSupport
Chui Tey5d2af632002-05-26 13:36:41 +000039
Kurt B. Kaiserb9764192002-09-23 04:10:37 +000040IDENTCHARS = string.ascii_letters + string.digits + "_"
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +000041HOST = '127.0.0.1' # python execution server on localhost loopback
42PORT = 0 # someday pass in host, port for remote debug capability
Kurt B. Kaiserb9764192002-09-23 04:10:37 +000043
Kurt B. Kaisera00050f2003-05-08 20:26:55 +000044try:
45 from signal import SIGTERM
46except ImportError:
47 SIGTERM = 15
48
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000049# Override warnings module to write to warning_stream. Initialize to send IDLE
50# internal warnings to the console. ScriptBinding.check_syntax() will
51# temporarily redirect the stream to the shell window to display warnings when
52# checking user's code.
Terry Jan Reedy8eab0082013-06-28 23:51:34 -040053warning_stream = sys.__stderr__ # None, at least on Windows, if no console.
54import warnings
55
56def idle_formatwarning(message, category, filename, lineno, line=None):
57 """Format warnings the IDLE way."""
58
59 s = "\nWarning (from warnings module):\n"
60 s += ' File \"%s\", line %s\n' % (filename, lineno)
61 if line is None:
62 line = linecache.getline(filename, lineno)
63 line = line.strip()
64 if line:
65 s += " %s\n" % line
66 s += "%s: %s\n" % (category.__name__, message)
67 return s
68
69def idle_showwarning(
70 message, category, filename, lineno, file=None, line=None):
71 """Show Idle-format warning (after replacing warnings.showwarning).
72
73 The differences are the formatter called, the file=None replacement,
74 which can be None, the capture of the consequence AttributeError,
75 and the output of a hard-coded prompt.
76 """
77 if file is None:
78 file = warning_stream
79 try:
80 file.write(idle_formatwarning(
81 message, category, filename, lineno, line=line))
82 file.write(">>> ")
83 except (AttributeError, IOError):
84 pass # if file (probably __stderr__) is invalid, skip warning.
85
86_warnings_showwarning = None
87
88def capture_warnings(capture):
89 "Replace warning.showwarning with idle_showwarning, or reverse."
90
91 global _warnings_showwarning
92 if capture:
93 if _warnings_showwarning is None:
94 _warnings_showwarning = warnings.showwarning
95 warnings.showwarning = idle_showwarning
96 else:
97 if _warnings_showwarning is not None:
98 warnings.showwarning = _warnings_showwarning
99 _warnings_showwarning = None
100
101capture_warnings(True)
Chui Tey5d2af632002-05-26 13:36:41 +0000102
Kurt B. Kaiserf7a88992004-11-13 21:05:58 +0000103def extended_linecache_checkcache(filename=None,
104 orig_checkcache=linecache.checkcache):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000105 """Extend linecache.checkcache to preserve the <pyshell#...> entries
106
Kurt B. Kaiserf7a88992004-11-13 21:05:58 +0000107 Rather than repeating the linecache code, patch it to save the
108 <pyshell#...> entries, call the original linecache.checkcache()
Guilherme Polof198ac22009-08-14 14:03:07 +0000109 (skipping them), and then restore the saved entries.
Kurt B. Kaiserf7a88992004-11-13 21:05:58 +0000110
111 orig_checkcache is bound at definition time to the original
112 method, allowing it to be patched.
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000113 """
David Scherer7aced172000-08-15 01:13:23 +0000114 cache = linecache.cache
115 save = {}
Guilherme Polof198ac22009-08-14 14:03:07 +0000116 for key in list(cache):
117 if key[:1] + key[-1:] == '<>':
118 save[key] = cache.pop(key)
119 orig_checkcache(filename)
David Scherer7aced172000-08-15 01:13:23 +0000120 cache.update(save)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000121
Kurt B. Kaiser81885592002-11-29 22:10:53 +0000122# Patch linecache.checkcache():
123linecache.checkcache = extended_linecache_checkcache
David Scherer7aced172000-08-15 01:13:23 +0000124
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000125
David Scherer7aced172000-08-15 01:13:23 +0000126class PyShellEditorWindow(EditorWindow):
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000127 "Regular text edit window in IDLE, supports breakpoints"
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000128
David Scherer7aced172000-08-15 01:13:23 +0000129 def __init__(self, *args):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000130 self.breakpoints = []
Raymond Hettinger931237e2003-07-09 18:48:24 +0000131 EditorWindow.__init__(self, *args)
David Scherer7aced172000-08-15 01:13:23 +0000132 self.text.bind("<<set-breakpoint-here>>", self.set_breakpoint_here)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000133 self.text.bind("<<clear-breakpoint-here>>", self.clear_breakpoint_here)
David Scherer7aced172000-08-15 01:13:23 +0000134 self.text.bind("<<open-python-shell>>", self.flist.open_shell)
135
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000136 self.breakpointPath = os.path.join(idleConf.GetUserCfgDir(),
137 'breakpoints.lst')
Chui Teya2adb0f2002-11-04 22:14:54 +0000138 # whenever a file is changed, restore breakpoints
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000139 def filename_changed_hook(old_hook=self.io.filename_change_hook,
140 self=self):
Chui Teya2adb0f2002-11-04 22:14:54 +0000141 self.restore_file_breaks()
142 old_hook()
143 self.io.set_filename_change_hook(filename_changed_hook)
Roger Serwyd7c9d9c2013-04-02 22:37:12 -0500144 if self.io.filename:
145 self.restore_file_breaks()
Chui Teya2adb0f2002-11-04 22:14:54 +0000146
Andrew Svetlov5018db72012-11-01 22:39:14 +0200147 rmenu_specs = [
148 ("Cut", "<<cut>>", "rmenu_check_cut"),
149 ("Copy", "<<copy>>", "rmenu_check_copy"),
150 ("Paste", "<<paste>>", "rmenu_check_paste"),
151 ("Set Breakpoint", "<<set-breakpoint-here>>", None),
152 ("Clear Breakpoint", "<<clear-breakpoint-here>>", None)
153 ]
David Scherer7aced172000-08-15 01:13:23 +0000154
Chui Teya2adb0f2002-11-04 22:14:54 +0000155 def set_breakpoint(self, lineno):
156 text = self.text
157 filename = self.io.filename
158 text.tag_add("BREAK", "%d.0" % lineno, "%d.0" % (lineno+1))
159 try:
160 i = self.breakpoints.index(lineno)
161 except ValueError: # only add if missing, i.e. do once
162 self.breakpoints.append(lineno)
163 try: # update the subprocess debugger
164 debug = self.flist.pyshell.interp.debugger
165 debug.set_breakpoint_here(filename, lineno)
166 except: # but debugger may not be active right now....
167 pass
168
David Scherer7aced172000-08-15 01:13:23 +0000169 def set_breakpoint_here(self, event=None):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000170 text = self.text
171 filename = self.io.filename
172 if not filename:
173 text.bell()
David Scherer7aced172000-08-15 01:13:23 +0000174 return
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000175 lineno = int(float(text.index("insert")))
Chui Teya2adb0f2002-11-04 22:14:54 +0000176 self.set_breakpoint(lineno)
David Scherer7aced172000-08-15 01:13:23 +0000177
Kurt B. Kaiser669f4c32002-06-20 04:01:47 +0000178 def clear_breakpoint_here(self, event=None):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000179 text = self.text
180 filename = self.io.filename
181 if not filename:
182 text.bell()
Kurt B. Kaiser669f4c32002-06-20 04:01:47 +0000183 return
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000184 lineno = int(float(text.index("insert")))
185 try:
186 self.breakpoints.remove(lineno)
187 except:
188 pass
189 text.tag_remove("BREAK", "insert linestart",\
190 "insert lineend +1char")
191 try:
192 debug = self.flist.pyshell.interp.debugger
193 debug.clear_breakpoint_here(filename, lineno)
194 except:
195 pass
196
197 def clear_file_breaks(self):
198 if self.breakpoints:
199 text = self.text
200 filename = self.io.filename
201 if not filename:
202 text.bell()
203 return
204 self.breakpoints = []
205 text.tag_remove("BREAK", "1.0", END)
206 try:
207 debug = self.flist.pyshell.interp.debugger
208 debug.clear_file_breaks(filename)
209 except:
210 pass
211
Chui Teya2adb0f2002-11-04 22:14:54 +0000212 def store_file_breaks(self):
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000213 "Save breakpoints when file is saved"
214 # XXX 13 Dec 2002 KBK Currently the file must be saved before it can
215 # be run. The breaks are saved at that time. If we introduce
216 # a temporary file save feature the save breaks functionality
217 # needs to be re-verified, since the breaks at the time the
218 # temp file is created may differ from the breaks at the last
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000219 # permanent save of the file. Currently, a break introduced
220 # after a save will be effective, but not persistent.
221 # This is necessary to keep the saved breaks synched with the
222 # saved file.
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000223 #
224 # Breakpoints are set as tagged ranges in the text. Certain
225 # kinds of edits cause these ranges to be deleted: Inserting
226 # or deleting a line just before a breakpoint, and certain
227 # deletions prior to a breakpoint. These issues need to be
228 # investigated and understood. It's not clear if they are
229 # Tk issues or IDLE issues, or whether they can actually
230 # be fixed. Since a modified file has to be saved before it is
231 # run, and since self.breakpoints (from which the subprocess
232 # debugger is loaded) is updated during the save, the visible
233 # breaks stay synched with the subprocess even if one of these
234 # unexpected breakpoint deletions occurs.
235 breaks = self.breakpoints
236 filename = self.io.filename
Chui Teya2adb0f2002-11-04 22:14:54 +0000237 try:
Ned Deily40ad0412011-12-14 14:57:43 -0800238 with open(self.breakpointPath,"r") as old_file:
239 lines = old_file.readlines()
Chui Teya2adb0f2002-11-04 22:14:54 +0000240 except IOError:
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000241 lines = []
Ned Deily40ad0412011-12-14 14:57:43 -0800242 try:
243 with open(self.breakpointPath,"w") as new_file:
244 for line in lines:
245 if not line.startswith(filename + '='):
246 new_file.write(line)
247 self.update_breakpoints()
248 breaks = self.breakpoints
249 if breaks:
250 new_file.write(filename + '=' + str(breaks) + '\n')
251 except IOError as err:
252 if not getattr(self.root, "breakpoint_error_displayed", False):
253 self.root.breakpoint_error_displayed = True
254 tkMessageBox.showerror(title='IDLE Error',
255 message='Unable to update breakpoint list:\n%s'
256 % str(err),
257 parent=self.text)
Chui Teya2adb0f2002-11-04 22:14:54 +0000258
259 def restore_file_breaks(self):
260 self.text.update() # this enables setting "BREAK" tags to be visible
Roger Serwyd7c9d9c2013-04-02 22:37:12 -0500261 if self.io is None:
262 # can happen if IDLE closes due to the .update() call
263 return
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000264 filename = self.io.filename
265 if filename is None:
266 return
Chui Tey69371d62002-11-04 23:39:45 +0000267 if os.path.isfile(self.breakpointPath):
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000268 lines = open(self.breakpointPath,"r").readlines()
Chui Tey69371d62002-11-04 23:39:45 +0000269 for line in lines:
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000270 if line.startswith(filename + '='):
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000271 breakpoint_linenumbers = eval(line[len(filename)+1:])
Chui Tey69371d62002-11-04 23:39:45 +0000272 for breakpoint_linenumber in breakpoint_linenumbers:
273 self.set_breakpoint(breakpoint_linenumber)
Chui Teya2adb0f2002-11-04 22:14:54 +0000274
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000275 def update_breakpoints(self):
276 "Retrieves all the breakpoints in the current window"
Chui Teya2adb0f2002-11-04 22:14:54 +0000277 text = self.text
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000278 ranges = text.tag_ranges("BREAK")
279 linenumber_list = self.ranges_to_linenumbers(ranges)
280 self.breakpoints = linenumber_list
281
282 def ranges_to_linenumbers(self, ranges):
283 lines = []
284 for index in range(0, len(ranges), 2):
Andrew Svetlov8a15c372012-07-31 19:51:27 +0300285 lineno = int(float(ranges[index].string))
286 end = int(float(ranges[index+1].string))
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000287 while lineno < end:
288 lines.append(lineno)
289 lineno += 1
290 return lines
291
Kurt B. Kaiser11220fa2002-12-24 00:57:22 +0000292# XXX 13 Dec 2002 KBK Not used currently
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000293# def saved_change_hook(self):
294# "Extend base method - clear breaks if module is modified"
295# if not self.get_saved():
296# self.clear_file_breaks()
297# EditorWindow.saved_change_hook(self)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000298
299 def _close(self):
300 "Extend base method - clear breaks when module is closed"
301 self.clear_file_breaks()
302 EditorWindow._close(self)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000303
David Scherer7aced172000-08-15 01:13:23 +0000304
305class PyShellFileList(FileList):
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000306 "Extend base class: IDLE supports a shell and breakpoints"
David Scherer7aced172000-08-15 01:13:23 +0000307
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000308 # override FileList's class variable, instances return PyShellEditorWindow
309 # instead of EditorWindow when new edit windows are created.
David Scherer7aced172000-08-15 01:13:23 +0000310 EditorWindow = PyShellEditorWindow
311
312 pyshell = None
313
314 def open_shell(self, event=None):
315 if self.pyshell:
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000316 self.pyshell.top.wakeup()
David Scherer7aced172000-08-15 01:13:23 +0000317 else:
318 self.pyshell = PyShell(self)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000319 if self.pyshell:
320 if not self.pyshell.begin():
321 return None
David Scherer7aced172000-08-15 01:13:23 +0000322 return self.pyshell
323
324
325class ModifiedColorDelegator(ColorDelegator):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000326 "Extend base class: colorizer for the shell window itself"
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000327
Steven M. Gavab77d3432002-03-02 07:16:21 +0000328 def __init__(self):
329 ColorDelegator.__init__(self)
330 self.LoadTagDefs()
David Scherer7aced172000-08-15 01:13:23 +0000331
332 def recolorize_main(self):
333 self.tag_remove("TODO", "1.0", "iomark")
334 self.tag_add("SYNC", "1.0", "iomark")
335 ColorDelegator.recolorize_main(self)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000336
Steven M. Gavab77d3432002-03-02 07:16:21 +0000337 def LoadTagDefs(self):
338 ColorDelegator.LoadTagDefs(self)
339 theme = idleConf.GetOption('main','Theme','name')
340 self.tagdefs.update({
341 "stdin": {'background':None,'foreground':None},
342 "stdout": idleConf.GetHighlight(theme, "stdout"),
343 "stderr": idleConf.GetHighlight(theme, "stderr"),
344 "console": idleConf.GetHighlight(theme, "console"),
Steven M. Gavab77d3432002-03-02 07:16:21 +0000345 })
David Scherer7aced172000-08-15 01:13:23 +0000346
Ned Deily5e247b72012-05-31 09:17:29 -0700347 def removecolors(self):
348 # Don't remove shell color tags before "iomark"
349 for tag in self.tagdefs:
350 self.tag_remove(tag, "iomark", "end")
351
David Scherer7aced172000-08-15 01:13:23 +0000352class ModifiedUndoDelegator(UndoDelegator):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000353 "Extend base class: forbid insert/delete before the I/O mark"
David Scherer7aced172000-08-15 01:13:23 +0000354
355 def insert(self, index, chars, tags=None):
356 try:
357 if self.delegate.compare(index, "<", "iomark"):
358 self.delegate.bell()
359 return
360 except TclError:
361 pass
362 UndoDelegator.insert(self, index, chars, tags)
363
364 def delete(self, index1, index2=None):
365 try:
366 if self.delegate.compare(index1, "<", "iomark"):
367 self.delegate.bell()
368 return
369 except TclError:
370 pass
371 UndoDelegator.delete(self, index1, index2)
372
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000373
374class MyRPCClient(rpc.RPCClient):
375
376 def handle_EOF(self):
377 "Override the base class - just re-raise EOFError"
378 raise EOFError
379
Kurt B. Kaiser8d1f11b2003-05-26 22:20:34 +0000380
David Scherer7aced172000-08-15 01:13:23 +0000381class ModifiedInterpreter(InteractiveInterpreter):
382
383 def __init__(self, tkconsole):
384 self.tkconsole = tkconsole
385 locals = sys.modules['__main__'].__dict__
386 InteractiveInterpreter.__init__(self, locals=locals)
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000387 self.save_warnings_filters = None
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000388 self.restarting = False
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +0000389 self.subprocess_arglist = None
390 self.port = PORT
Ned Deily86d669b2011-10-30 19:58:04 -0700391 self.original_compiler_flags = self.compile.compiler.flags
David Scherer7aced172000-08-15 01:13:23 +0000392
Roger Serwy16ce43a2013-06-11 22:13:17 -0500393 _afterid = None
Chui Tey5d2af632002-05-26 13:36:41 +0000394 rpcclt = None
395 rpcpid = None
396
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000397 def spawn_subprocess(self):
Florent Xiclunac8a730b2010-03-25 20:32:07 +0000398 if self.subprocess_arglist is None:
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +0000399 self.subprocess_arglist = self.build_subprocess_arglist()
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000400 args = self.subprocess_arglist
Kurt B. Kaiserb7855182003-08-14 14:54:28 +0000401 self.rpcpid = os.spawnv(os.P_NOWAIT, sys.executable, args)
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000402
Tony Lowndsf53dec22002-12-20 04:24:43 +0000403 def build_subprocess_arglist(self):
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +0000404 assert (self.port!=0), (
405 "Socket should have been assigned a port number.")
Tony Lownds2398d572003-05-13 15:28:21 +0000406 w = ['-W' + s for s in sys.warnoptions]
Georg Brandld0761532006-10-12 07:57:21 +0000407 if 1/2 > 0: # account for new division
408 w.append('-Qnew')
Tony Lownds2398d572003-05-13 15:28:21 +0000409 # Maybe IDLE is installed and is being accessed via sys.path,
410 # or maybe it's not installed and the idle.py script is being
411 # run from the IDLE source directory.
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000412 del_exitf = idleConf.GetOption('main', 'General', 'delete-exitfunc',
413 default=False, type='bool')
Tony Lownds2398d572003-05-13 15:28:21 +0000414 if __name__ == 'idlelib.PyShell':
Walter Dörwald70a6b492004-02-12 17:35:32 +0000415 command = "__import__('idlelib.run').run.main(%r)" % (del_exitf,)
Tony Lowndsf2324b92002-09-29 00:34:10 +0000416 else:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000417 command = "__import__('run').main(%r)" % (del_exitf,)
Kurt B. Kaiserb7855182003-08-14 14:54:28 +0000418 if sys.platform[:3] == 'win' and ' ' in sys.executable:
419 # handle embedded space in path by quoting the argument
420 decorated_exec = '"%s"' % sys.executable
421 else:
422 decorated_exec = sys.executable
423 return [decorated_exec] + w + ["-c", command, str(self.port)]
Tony Lowndsf2324b92002-09-29 00:34:10 +0000424
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000425 def start_subprocess(self):
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +0000426 addr = (HOST, self.port)
427 # GUI makes several attempts to acquire socket, listens for connection
Kurt B. Kaiser5db48432003-05-15 03:40:51 +0000428 for i in range(3):
Chui Tey5d2af632002-05-26 13:36:41 +0000429 time.sleep(i)
430 try:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000431 self.rpcclt = MyRPCClient(addr)
Chui Tey5d2af632002-05-26 13:36:41 +0000432 break
Terry Jan Reedy2b149862013-06-29 00:59:34 -0400433 except socket.error as err:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000434 pass
Chui Tey5d2af632002-05-26 13:36:41 +0000435 else:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000436 self.display_port_binding_error()
437 return None
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +0000438 # if PORT was 0, system will assign an 'ephemeral' port. Find it out:
439 self.port = self.rpcclt.listening_sock.getsockname()[1]
440 # if PORT was not 0, probably working with a remote execution server
441 if PORT != 0:
442 # To allow reconnection within the 2MSL wait (cf. Stevens TCP
443 # V1, 18.6), set SO_REUSEADDR. Note that this can be problematic
444 # on Windows since the implementation allows two active sockets on
445 # the same address!
446 self.rpcclt.listening_sock.setsockopt(socket.SOL_SOCKET,
447 socket.SO_REUSEADDR, 1)
448 self.spawn_subprocess()
449 #time.sleep(20) # test to simulate GUI not accepting connection
Kurt B. Kaiserb4179362002-07-26 00:06:42 +0000450 # Accept the connection from the Python execution server
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000451 self.rpcclt.listening_sock.settimeout(10)
452 try:
453 self.rpcclt.accept()
Terry Jan Reedy2b149862013-06-29 00:59:34 -0400454 except socket.timeout as err:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000455 self.display_no_subprocess_error()
456 return None
Serhiy Storchaka9abc8302013-01-25 15:30:35 +0200457 self.rpcclt.register("console", self.tkconsole)
458 self.rpcclt.register("stdin", self.tkconsole.stdin)
Kurt B. Kaiser969de452002-06-12 03:28:57 +0000459 self.rpcclt.register("stdout", self.tkconsole.stdout)
460 self.rpcclt.register("stderr", self.tkconsole.stderr)
Chui Tey5d2af632002-05-26 13:36:41 +0000461 self.rpcclt.register("flist", self.tkconsole.flist)
Kurt B. Kaiser8cd0def2003-01-31 05:06:43 +0000462 self.rpcclt.register("linecache", linecache)
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000463 self.rpcclt.register("interp", self)
Terry Jan Reedyb98000a2012-01-31 02:09:25 -0500464 self.transfer_path(with_cwd=True)
Chui Tey5d2af632002-05-26 13:36:41 +0000465 self.poll_subprocess()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000466 return self.rpcclt
Chui Tey5d2af632002-05-26 13:36:41 +0000467
Terry Jan Reedyb98000a2012-01-31 02:09:25 -0500468 def restart_subprocess(self, with_cwd=False):
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000469 if self.restarting:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000470 return self.rpcclt
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000471 self.restarting = True
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000472 # close only the subprocess debugger
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000473 debug = self.getdebugger()
474 if debug:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000475 try:
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000476 # Only close subprocess debugger, don't unregister gui_adap!
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000477 RemoteDebugger.close_subprocess_debugger(self.rpcclt)
478 except:
479 pass
480 # Kill subprocess, spawn a new one, accept connection.
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000481 self.rpcclt.close()
482 self.unix_terminate()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000483 console = self.tkconsole
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000484 was_executing = console.executing
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000485 console.executing = False
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000486 self.spawn_subprocess()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000487 try:
488 self.rpcclt.accept()
Terry Jan Reedy2b149862013-06-29 00:59:34 -0400489 except socket.timeout as err:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000490 self.display_no_subprocess_error()
491 return None
Terry Jan Reedyb98000a2012-01-31 02:09:25 -0500492 self.transfer_path(with_cwd=with_cwd)
Roger Serwyad8cad32013-04-03 00:42:24 -0500493 console.stop_readline()
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000494 # annotate restart in shell window and mark it
Kurt B. Kaiser4cc5ef52003-01-22 00:23:23 +0000495 console.text.delete("iomark", "end-1c")
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000496 if was_executing:
497 console.write('\n')
498 console.showprompt()
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000499 halfbar = ((int(console.width) - 16) // 2) * '='
500 console.write(halfbar + ' RESTART ' + halfbar)
501 console.text.mark_set("restart", "end-1c")
502 console.text.mark_gravity("restart", "left")
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000503 console.showprompt()
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000504 # restart subprocess debugger
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000505 if debug:
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000506 # Restarted debugger connects to current instance of debug GUI
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000507 gui = RemoteDebugger.restart_subprocess_debugger(self.rpcclt)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000508 # reload remote debugger breakpoints for all PyShellEditWindows
509 debug.load_breakpoints()
Ned Deily86d669b2011-10-30 19:58:04 -0700510 self.compile.compiler.flags = self.original_compiler_flags
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000511 self.restarting = False
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000512 return self.rpcclt
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000513
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000514 def __request_interrupt(self):
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000515 self.rpcclt.remotecall("exec", "interrupt_the_server", (), {})
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000516
517 def interrupt_subprocess(self):
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000518 threading.Thread(target=self.__request_interrupt).start()
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000519
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000520 def kill_subprocess(self):
Roger Serwy16ce43a2013-06-11 22:13:17 -0500521 if self._afterid is not None:
522 self.tkconsole.text.after_cancel(self._afterid)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000523 try:
524 self.rpcclt.close()
525 except AttributeError: # no socket
526 pass
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000527 self.unix_terminate()
528 self.tkconsole.executing = False
529 self.rpcclt = None
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000530
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000531 def unix_terminate(self):
532 "UNIX: make sure subprocess is terminated and collect status"
533 if hasattr(os, 'kill'):
534 try:
535 os.kill(self.rpcpid, SIGTERM)
536 except OSError:
537 # process already terminated:
538 return
539 else:
540 try:
541 os.waitpid(self.rpcpid, 0)
542 except OSError:
543 return
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000544
Terry Jan Reedyb98000a2012-01-31 02:09:25 -0500545 def transfer_path(self, with_cwd=False):
546 if with_cwd: # Issue 13506
547 path = [''] # include Current Working Directory
548 path.extend(sys.path)
549 else:
550 path = sys.path
Terry Jan Reedy1d4ae482012-01-31 02:55:32 -0500551
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000552 self.runcommand("""if 1:
553 import sys as _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +0000554 _sys.path = %r
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000555 del _sys
Terry Jan Reedyb98000a2012-01-31 02:09:25 -0500556 \n""" % (path,))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000557
Chui Tey5d2af632002-05-26 13:36:41 +0000558 active_seq = None
559
560 def poll_subprocess(self):
561 clt = self.rpcclt
562 if clt is None:
563 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000564 try:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000565 response = clt.pollresponse(self.active_seq, wait=0.05)
566 except (EOFError, IOError, KeyboardInterrupt):
567 # lost connection or subprocess terminated itself, restart
568 # [the KBI is from rpc.SocketIO.handle_EOF()]
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000569 if self.tkconsole.closing:
570 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000571 response = None
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000572 self.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000573 if response:
574 self.tkconsole.resetoutput()
575 self.active_seq = None
576 how, what = response
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000577 console = self.tkconsole.console
Chui Tey5d2af632002-05-26 13:36:41 +0000578 if how == "OK":
579 if what is not None:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000580 print >>console, repr(what)
Chui Tey5d2af632002-05-26 13:36:41 +0000581 elif how == "EXCEPTION":
Chui Tey5d2af632002-05-26 13:36:41 +0000582 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
583 self.remote_stack_viewer()
584 elif how == "ERROR":
Kurt B. Kaiser0930c432002-12-06 21:45:24 +0000585 errmsg = "PyShell.ModifiedInterpreter: Subprocess ERROR:\n"
586 print >>sys.__stderr__, errmsg, what
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000587 print >>console, errmsg, what
588 # we received a response to the currently active seq number:
Kurt B. Kaiserd112bc72006-08-16 05:01:42 +0000589 try:
590 self.tkconsole.endexecuting()
591 except AttributeError: # shell may have closed
592 pass
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000593 # Reschedule myself
594 if not self.tkconsole.closing:
Roger Serwy16ce43a2013-06-11 22:13:17 -0500595 self._afterid = self.tkconsole.text.after(
596 self.tkconsole.pollinterval, self.poll_subprocess)
Chui Tey5d2af632002-05-26 13:36:41 +0000597
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000598 debugger = None
599
600 def setdebugger(self, debugger):
601 self.debugger = debugger
602
603 def getdebugger(self):
604 return self.debugger
605
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000606 def open_remote_stack_viewer(self):
607 """Initiate the remote stack viewer from a separate thread.
608
609 This method is called from the subprocess, and by returning from this
610 method we allow the subprocess to unblock. After a bit the shell
611 requests the subprocess to open the remote stack viewer which returns a
Ezio Melottic569cfe2010-07-23 16:55:21 +0000612 static object looking at the last exception. It is queried through
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000613 the RPC mechanism.
614
615 """
616 self.tkconsole.text.after(300, self.remote_stack_viewer)
617 return
618
Chui Tey5d2af632002-05-26 13:36:41 +0000619 def remote_stack_viewer(self):
Florent Xiclunad630c042010-04-02 07:24:52 +0000620 from idlelib import RemoteObjectBrowser
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000621 oid = self.rpcclt.remotequeue("exec", "stackviewer", ("flist",), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000622 if oid is None:
623 self.tkconsole.root.bell()
624 return
625 item = RemoteObjectBrowser.StubObjectTreeItem(self.rpcclt, oid)
Florent Xiclunad630c042010-04-02 07:24:52 +0000626 from idlelib.TreeWidget import ScrolledCanvas, TreeNode
Chui Tey5d2af632002-05-26 13:36:41 +0000627 top = Toplevel(self.tkconsole.root)
Kurt B. Kaiser73360a32004-03-08 18:15:31 +0000628 theme = idleConf.GetOption('main','Theme','name')
629 background = idleConf.GetHighlight(theme, 'normal')['background']
630 sc = ScrolledCanvas(top, bg=background, highlightthickness=0)
Chui Tey5d2af632002-05-26 13:36:41 +0000631 sc.frame.pack(expand=1, fill="both")
632 node = TreeNode(sc.canvas, None, item)
633 node.expand()
634 # XXX Should GC the remote tree when closing the window
635
David Scherer7aced172000-08-15 01:13:23 +0000636 gid = 0
637
638 def execsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000639 "Like runsource() but assumes complete exec source"
David Scherer7aced172000-08-15 01:13:23 +0000640 filename = self.stuffsource(source)
641 self.execfile(filename, source)
642
643 def execfile(self, filename, source=None):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000644 "Execute an existing file"
David Scherer7aced172000-08-15 01:13:23 +0000645 if source is None:
646 source = open(filename, "r").read()
647 try:
648 code = compile(source, filename, "exec")
649 except (OverflowError, SyntaxError):
650 self.tkconsole.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000651 tkerr = self.tkconsole.stderr
652 print>>tkerr, '*** Error in script or command!\n'
653 print>>tkerr, 'Traceback (most recent call last):'
David Scherer7aced172000-08-15 01:13:23 +0000654 InteractiveInterpreter.showsyntaxerror(self, filename)
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000655 self.tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000656 else:
657 self.runcode(code)
658
659 def runsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000660 "Extend base class method: Stuff the source in the line cache first"
David Scherer7aced172000-08-15 01:13:23 +0000661 filename = self.stuffsource(source)
662 self.more = 0
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000663 self.save_warnings_filters = warnings.filters[:]
664 warnings.filterwarnings(action="error", category=SyntaxWarning)
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000665 if isinstance(source, types.UnicodeType):
Florent Xiclunad630c042010-04-02 07:24:52 +0000666 from idlelib import IOBinding
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000667 try:
668 source = source.encode(IOBinding.encoding)
669 except UnicodeError:
670 self.tkconsole.resetoutput()
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +0000671 self.write("Unsupported characters in input\n")
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000672 return
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000673 try:
Kurt B. Kaiser935ea9a2005-05-10 03:44:24 +0000674 # InteractiveInterpreter.runsource() calls its runcode() method,
675 # which is overridden (see below)
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000676 return InteractiveInterpreter.runsource(self, source, filename)
677 finally:
678 if self.save_warnings_filters is not None:
679 warnings.filters[:] = self.save_warnings_filters
680 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000681
682 def stuffsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000683 "Stuff source in the filename cache"
David Scherer7aced172000-08-15 01:13:23 +0000684 filename = "<pyshell#%d>" % self.gid
685 self.gid = self.gid + 1
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000686 lines = source.split("\n")
David Scherer7aced172000-08-15 01:13:23 +0000687 linecache.cache[filename] = len(source)+1, 0, lines, filename
688 return filename
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000689
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000690 def prepend_syspath(self, filename):
691 "Prepend sys.path with file's directory if not already included"
692 self.runcommand("""if 1:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000693 _filename = %r
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000694 import sys as _sys
695 from os.path import dirname as _dirname
696 _dir = _dirname(_filename)
697 if not _dir in _sys.path:
698 _sys.path.insert(0, _dir)
699 del _filename, _sys, _dirname, _dir
Walter Dörwald70a6b492004-02-12 17:35:32 +0000700 \n""" % (filename,))
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000701
David Scherer7aced172000-08-15 01:13:23 +0000702 def showsyntaxerror(self, filename=None):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000703 """Extend base class method: Add Colorizing
704
705 Color the offending position instead of printing it and pointing at it
706 with a caret.
707
708 """
David Scherer7aced172000-08-15 01:13:23 +0000709 text = self.tkconsole.text
710 stuff = self.unpackerror()
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000711 if stuff:
712 msg, lineno, offset, line = stuff
713 if lineno == 1:
714 pos = "iomark + %d chars" % (offset-1)
715 else:
716 pos = "iomark linestart + %d lines + %d chars" % \
717 (lineno-1, offset-1)
718 text.tag_add("ERROR", pos)
719 text.see(pos)
720 char = text.get(pos)
721 if char and char in IDENTCHARS:
722 text.tag_add("ERROR", pos + " wordstart", pos)
723 self.tkconsole.resetoutput()
724 self.write("SyntaxError: %s\n" % str(msg))
725 else:
David Scherer7aced172000-08-15 01:13:23 +0000726 self.tkconsole.resetoutput()
727 InteractiveInterpreter.showsyntaxerror(self, filename)
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000728 self.tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000729
730 def unpackerror(self):
731 type, value, tb = sys.exc_info()
732 ok = type is SyntaxError
733 if ok:
734 try:
735 msg, (dummy_filename, lineno, offset, line) = value
Kurt B. Kaiserbea57c62003-07-09 04:27:24 +0000736 if not offset:
737 offset = 0
David Scherer7aced172000-08-15 01:13:23 +0000738 except:
739 ok = 0
740 if ok:
741 return msg, lineno, offset, line
742 else:
743 return None
744
745 def showtraceback(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000746 "Extend base class method to reset output properly"
David Scherer7aced172000-08-15 01:13:23 +0000747 self.tkconsole.resetoutput()
748 self.checklinecache()
749 InteractiveInterpreter.showtraceback(self)
Chui Tey5d2af632002-05-26 13:36:41 +0000750 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
751 self.tkconsole.open_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +0000752
753 def checklinecache(self):
754 c = linecache.cache
755 for key in c.keys():
756 if key[:1] + key[-1:] != "<>":
757 del c[key]
758
Chui Tey5d2af632002-05-26 13:36:41 +0000759 def runcommand(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000760 "Run the code without invoking the debugger"
Chui Tey5d2af632002-05-26 13:36:41 +0000761 # The code better not raise an exception!
762 if self.tkconsole.executing:
Neal Norwitzf4c4f112002-11-30 18:49:10 +0000763 self.display_executing_dialog()
Chui Tey5d2af632002-05-26 13:36:41 +0000764 return 0
765 if self.rpcclt:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000766 self.rpcclt.remotequeue("exec", "runcode", (code,), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000767 else:
768 exec code in self.locals
769 return 1
770
David Scherer7aced172000-08-15 01:13:23 +0000771 def runcode(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000772 "Override base class method"
Chui Tey5d2af632002-05-26 13:36:41 +0000773 if self.tkconsole.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000774 self.interp.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000775 self.checklinecache()
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000776 if self.save_warnings_filters is not None:
777 warnings.filters[:] = self.save_warnings_filters
778 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000779 debugger = self.debugger
780 try:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000781 self.tkconsole.beginexecuting()
Kurt B. Kaiserdddeb0e2007-02-06 03:21:40 +0000782 if not debugger and self.rpcclt is not None:
783 self.active_seq = self.rpcclt.asyncqueue("exec", "runcode",
784 (code,), {})
785 elif debugger:
786 debugger.run(code, self.locals)
787 else:
788 exec code in self.locals
789 except SystemExit:
790 if not self.tkconsole.closing:
791 if tkMessageBox.askyesno(
792 "Exit?",
793 "Do you want to exit altogether?",
794 default="yes",
795 master=self.tkconsole.text):
Kurt B. Kaiserf137e1d2006-08-16 07:04:17 +0000796 raise
Kurt B. Kaiserdddeb0e2007-02-06 03:21:40 +0000797 else:
798 self.showtraceback()
799 else:
800 raise
801 except:
802 if use_subprocess:
803 print >>self.tkconsole.stderr, \
804 "IDLE internal error in runcode()"
David Scherer7aced172000-08-15 01:13:23 +0000805 self.showtraceback()
Kurt B. Kaiserdddeb0e2007-02-06 03:21:40 +0000806 self.tkconsole.endexecuting()
807 else:
808 if self.tkconsole.canceled:
809 self.tkconsole.canceled = False
810 print >>self.tkconsole.stderr, "KeyboardInterrupt"
811 else:
812 self.showtraceback()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000813 finally:
814 if not use_subprocess:
Kurt B. Kaiserd112bc72006-08-16 05:01:42 +0000815 try:
816 self.tkconsole.endexecuting()
817 except AttributeError: # shell may have closed
818 pass
David Scherer7aced172000-08-15 01:13:23 +0000819
820 def write(self, s):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000821 "Override base class method"
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000822 self.tkconsole.stderr.write(s)
David Scherer7aced172000-08-15 01:13:23 +0000823
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000824 def display_port_binding_error(self):
825 tkMessageBox.showerror(
826 "Port Binding Error",
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +0000827 "IDLE can't bind to a TCP/IP port, which is necessary to "
828 "communicate with its Python execution server. This might be "
829 "because no networking is installed on this computer. "
830 "Run IDLE with the -n command line switch to start without a "
831 "subprocess and refer to Help/IDLE Help 'Running without a "
832 "subprocess' for further details.",
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000833 master=self.tkconsole.text)
834
835 def display_no_subprocess_error(self):
836 tkMessageBox.showerror(
837 "Subprocess Startup Error",
838 "IDLE's subprocess didn't make connection. Either IDLE can't "
839 "start a subprocess or personal firewall software is blocking "
840 "the connection.",
841 master=self.tkconsole.text)
842
843 def display_executing_dialog(self):
844 tkMessageBox.showerror(
845 "Already executing",
846 "The Python Shell window is already executing a command; "
847 "please wait until it is finished.",
848 master=self.tkconsole.text)
849
850
David Scherer7aced172000-08-15 01:13:23 +0000851class PyShell(OutputWindow):
852
Terry Jan Reedyd676a3a2013-03-30 18:50:43 -0400853 shell_title = "Python " + python_version() + " Shell"
David Scherer7aced172000-08-15 01:13:23 +0000854
855 # Override classes
856 ColorDelegator = ModifiedColorDelegator
857 UndoDelegator = ModifiedUndoDelegator
858
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000859 # Override menus
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000860 menu_specs = [
861 ("file", "_File"),
862 ("edit", "_Edit"),
Kurt B. Kaiser4cc5ef52003-01-22 00:23:23 +0000863 ("debug", "_Debug"),
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000864 ("options", "_Options"),
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000865 ("windows", "_Windows"),
866 ("help", "_Help"),
867 ]
David Scherer7aced172000-08-15 01:13:23 +0000868
Ronald Oussoren19302d92006-06-11 14:33:36 +0000869 if macosxSupport.runningAsOSXApp():
Ronald Oussoren19302d92006-06-11 14:33:36 +0000870 menu_specs[-2] = ("windows", "_Window")
871
872
David Scherer7aced172000-08-15 01:13:23 +0000873 # New classes
Florent Xiclunad630c042010-04-02 07:24:52 +0000874 from idlelib.IdleHistory import History
David Scherer7aced172000-08-15 01:13:23 +0000875
876 def __init__(self, flist=None):
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000877 if use_subprocess:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000878 ms = self.menu_specs
879 if ms[2][0] != "shell":
Kurt B. Kaiser7ae35482006-08-16 21:45:59 +0000880 ms.insert(2, ("shell", "She_ll"))
David Scherer7aced172000-08-15 01:13:23 +0000881 self.interp = ModifiedInterpreter(self)
882 if flist is None:
883 root = Tk()
884 fixwordbreaks(root)
885 root.withdraw()
886 flist = PyShellFileList(root)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000887 #
David Scherer7aced172000-08-15 01:13:23 +0000888 OutputWindow.__init__(self, flist, None, None)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000889 #
Kurt B. Kaiser6af44982005-01-19 00:22:59 +0000890## self.config(usetabs=1, indentwidth=8, context_use_ps1=1)
891 self.usetabs = True
892 # indentwidth must be 8 when using tabs. See note in EditorWindow:
893 self.indentwidth = 8
894 self.context_use_ps1 = True
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000895 #
David Scherer7aced172000-08-15 01:13:23 +0000896 text = self.text
897 text.configure(wrap="char")
898 text.bind("<<newline-and-indent>>", self.enter_callback)
899 text.bind("<<plain-newline-and-indent>>", self.linefeed_callback)
900 text.bind("<<interrupt-execution>>", self.cancel_callback)
David Scherer7aced172000-08-15 01:13:23 +0000901 text.bind("<<end-of-file>>", self.eof_callback)
902 text.bind("<<open-stack-viewer>>", self.open_stack_viewer)
Kurt B. Kaiser57bfe5d2003-05-10 00:09:52 +0000903 text.bind("<<toggle-debugger>>", self.toggle_debugger)
David Scherer7aced172000-08-15 01:13:23 +0000904 text.bind("<<toggle-jit-stack-viewer>>", self.toggle_jit_stack_viewer)
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000905 if use_subprocess:
906 text.bind("<<view-restart>>", self.view_restart_mark)
907 text.bind("<<restart-shell>>", self.restart_shell)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000908 #
David Scherer7aced172000-08-15 01:13:23 +0000909 self.save_stdout = sys.stdout
910 self.save_stderr = sys.stderr
911 self.save_stdin = sys.stdin
Florent Xiclunad630c042010-04-02 07:24:52 +0000912 from idlelib import IOBinding
Serhiy Storchaka9abc8302013-01-25 15:30:35 +0200913 self.stdin = PseudoInputFile(self, "stdin", IOBinding.encoding)
914 self.stdout = PseudoOutputFile(self, "stdout", IOBinding.encoding)
915 self.stderr = PseudoOutputFile(self, "stderr", IOBinding.encoding)
916 self.console = PseudoOutputFile(self, "console", IOBinding.encoding)
Chui Tey5d2af632002-05-26 13:36:41 +0000917 if not use_subprocess:
918 sys.stdout = self.stdout
919 sys.stderr = self.stderr
Martin v. Löwise2b56242012-07-25 10:56:22 +0200920 sys.stdin = self.stdin
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000921 #
David Scherer7aced172000-08-15 01:13:23 +0000922 self.history = self.History(self.text)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000923 #
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000924 self.pollinterval = 50 # millisec
Chui Tey5d2af632002-05-26 13:36:41 +0000925
Kurt B. Kaiser4d5bc602004-06-06 01:29:22 +0000926 def get_standard_extension_names(self):
927 return idleConf.GetExtensions(shell_only=True)
928
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000929 reading = False
930 executing = False
931 canceled = False
932 endoffile = False
933 closing = False
Roger Serwyad8cad32013-04-03 00:42:24 -0500934 _stop_readline_flag = False
David Scherer7aced172000-08-15 01:13:23 +0000935
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +0000936 def set_warning_stream(self, stream):
Skip Montanarod9161422004-07-06 21:53:27 +0000937 global warning_stream
938 warning_stream = stream
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +0000939
940 def get_warning_stream(self):
941 return warning_stream
942
David Scherer7aced172000-08-15 01:13:23 +0000943 def toggle_debugger(self, event=None):
944 if self.executing:
945 tkMessageBox.showerror("Don't debug now",
946 "You can only toggle the debugger when idle",
947 master=self.text)
948 self.set_debugger_indicator()
949 return "break"
950 else:
951 db = self.interp.getdebugger()
952 if db:
953 self.close_debugger()
954 else:
955 self.open_debugger()
956
957 def set_debugger_indicator(self):
958 db = self.interp.getdebugger()
959 self.setvar("<<toggle-debugger>>", not not db)
960
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000961 def toggle_jit_stack_viewer(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +0000962 pass # All we need is the variable
963
964 def close_debugger(self):
965 db = self.interp.getdebugger()
966 if db:
967 self.interp.setdebugger(None)
968 db.close()
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000969 if self.interp.rpcclt:
970 RemoteDebugger.close_remote_debugger(self.interp.rpcclt)
David Scherer7aced172000-08-15 01:13:23 +0000971 self.resetoutput()
972 self.console.write("[DEBUG OFF]\n")
973 sys.ps1 = ">>> "
974 self.showprompt()
975 self.set_debugger_indicator()
976
977 def open_debugger(self):
Chui Tey5d2af632002-05-26 13:36:41 +0000978 if self.interp.rpcclt:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000979 dbg_gui = RemoteDebugger.start_remote_debugger(self.interp.rpcclt,
980 self)
981 else:
982 dbg_gui = Debugger.Debugger(self)
983 self.interp.setdebugger(dbg_gui)
984 dbg_gui.load_breakpoints()
Chui Tey5d2af632002-05-26 13:36:41 +0000985 sys.ps1 = "[DEBUG ON]\n>>> "
986 self.showprompt()
987 self.set_debugger_indicator()
988
David Scherer7aced172000-08-15 01:13:23 +0000989 def beginexecuting(self):
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000990 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +0000991 self.resetoutput()
992 self.executing = 1
David Scherer7aced172000-08-15 01:13:23 +0000993
994 def endexecuting(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000995 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +0000996 self.executing = 0
997 self.canceled = 0
Chui Tey5d2af632002-05-26 13:36:41 +0000998 self.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000999
1000 def close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +00001001 "Extend EditorWindow.close()"
David Scherer7aced172000-08-15 01:13:23 +00001002 if self.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001003 response = tkMessageBox.askokcancel(
David Scherer7aced172000-08-15 01:13:23 +00001004 "Kill?",
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001005 "The program is still running!\n Do you want to kill it?",
David Scherer7aced172000-08-15 01:13:23 +00001006 default="ok",
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001007 parent=self.text)
Benjamin Peterson5b63acd2008-03-29 15:24:25 +00001008 if response is False:
David Scherer7aced172000-08-15 01:13:23 +00001009 return "cancel"
Roger Serwyad8cad32013-04-03 00:42:24 -05001010 self.stop_readline()
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001011 self.canceled = True
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +00001012 self.closing = True
Kurt B. Kaiser88957d82003-05-19 23:11:51 +00001013 return EditorWindow.close(self)
David Scherer7aced172000-08-15 01:13:23 +00001014
1015 def _close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +00001016 "Extend EditorWindow._close(), shut down debugger and execution server"
David Scherer7aced172000-08-15 01:13:23 +00001017 self.close_debugger()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001018 if use_subprocess:
1019 self.interp.kill_subprocess()
David Scherer7aced172000-08-15 01:13:23 +00001020 # Restore std streams
1021 sys.stdout = self.save_stdout
1022 sys.stderr = self.save_stderr
1023 sys.stdin = self.save_stdin
1024 # Break cycles
1025 self.interp = None
1026 self.console = None
David Scherer7aced172000-08-15 01:13:23 +00001027 self.flist.pyshell = None
1028 self.history = None
Kurt B. Kaiser83118c62002-06-24 17:03:37 +00001029 EditorWindow._close(self)
David Scherer7aced172000-08-15 01:13:23 +00001030
1031 def ispythonsource(self, filename):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +00001032 "Override EditorWindow method: never remove the colorizer"
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001033 return True
David Scherer7aced172000-08-15 01:13:23 +00001034
1035 def short_title(self):
1036 return self.shell_title
1037
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +00001038 COPYRIGHT = \
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001039 'Type "copyright", "credits" or "license()" for more information.'
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +00001040
David Scherer7aced172000-08-15 01:13:23 +00001041 def begin(self):
1042 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001043 if use_subprocess:
1044 nosub = ''
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001045 client = self.interp.start_subprocess()
1046 if not client:
1047 self.close()
Kurt B. Kaiser76637292004-01-21 22:10:01 +00001048 return False
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001049 else:
1050 nosub = "==== No Subprocess ===="
Raymond Hettingerbf3f69e2009-01-26 23:29:09 +00001051 self.write("Python %s on %s\n%s\n%s" %
1052 (sys.version, sys.platform, self.COPYRIGHT, nosub))
David Scherer7aced172000-08-15 01:13:23 +00001053 self.showprompt()
Georg Brandl6634bf22008-05-20 07:13:37 +00001054 import Tkinter
1055 Tkinter._default_root = None # 03Jan04 KBK What's this?
Kurt B. Kaiser76637292004-01-21 22:10:01 +00001056 return True
David Scherer7aced172000-08-15 01:13:23 +00001057
Roger Serwyad8cad32013-04-03 00:42:24 -05001058 def stop_readline(self):
1059 if not self.reading: # no nested mainloop to exit.
1060 return
1061 self._stop_readline_flag = True
1062 self.top.quit()
1063
David Scherer7aced172000-08-15 01:13:23 +00001064 def readline(self):
1065 save = self.reading
1066 try:
1067 self.reading = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001068 self.top.mainloop() # nested mainloop()
David Scherer7aced172000-08-15 01:13:23 +00001069 finally:
1070 self.reading = save
Roger Serwyad8cad32013-04-03 00:42:24 -05001071 if self._stop_readline_flag:
1072 self._stop_readline_flag = False
1073 return ""
David Scherer7aced172000-08-15 01:13:23 +00001074 line = self.text.get("iomark", "end-1c")
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001075 if len(line) == 0: # may be EOF if we quit our mainloop with Ctrl-C
1076 line = "\n"
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001077 if isinstance(line, unicode):
Florent Xiclunad630c042010-04-02 07:24:52 +00001078 from idlelib import IOBinding
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001079 try:
1080 line = line.encode(IOBinding.encoding)
1081 except UnicodeError:
1082 pass
David Scherer7aced172000-08-15 01:13:23 +00001083 self.resetoutput()
1084 if self.canceled:
1085 self.canceled = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001086 if not use_subprocess:
1087 raise KeyboardInterrupt
David Scherer7aced172000-08-15 01:13:23 +00001088 if self.endoffile:
1089 self.endoffile = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001090 line = ""
David Scherer7aced172000-08-15 01:13:23 +00001091 return line
1092
1093 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001094 return True
David Scherer7aced172000-08-15 01:13:23 +00001095
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001096 def cancel_callback(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +00001097 try:
1098 if self.text.compare("sel.first", "!=", "sel.last"):
1099 return # Active selection -- always use default binding
1100 except:
1101 pass
1102 if not (self.executing or self.reading):
1103 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001104 self.interp.write("KeyboardInterrupt\n")
David Scherer7aced172000-08-15 01:13:23 +00001105 self.showprompt()
1106 return "break"
1107 self.endoffile = 0
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001108 self.canceled = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001109 if (self.executing and self.interp.rpcclt):
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +00001110 if self.interp.getdebugger():
1111 self.interp.restart_subprocess()
1112 else:
1113 self.interp.interrupt_subprocess()
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001114 if self.reading:
1115 self.top.quit() # exit the nested mainloop() in readline()
David Scherer7aced172000-08-15 01:13:23 +00001116 return "break"
1117
1118 def eof_callback(self, event):
1119 if self.executing and not self.reading:
1120 return # Let the default binding (delete next char) take over
1121 if not (self.text.compare("iomark", "==", "insert") and
1122 self.text.compare("insert", "==", "end-1c")):
1123 return # Let the default binding (delete next char) take over
1124 if not self.executing:
David Scherer7aced172000-08-15 01:13:23 +00001125 self.resetoutput()
1126 self.close()
1127 else:
1128 self.canceled = 0
1129 self.endoffile = 1
1130 self.top.quit()
1131 return "break"
1132
David Scherer7aced172000-08-15 01:13:23 +00001133 def linefeed_callback(self, event):
1134 # Insert a linefeed without entering anything (still autoindented)
1135 if self.reading:
1136 self.text.insert("insert", "\n")
1137 self.text.see("insert")
1138 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001139 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001140 return "break"
1141
1142 def enter_callback(self, event):
1143 if self.executing and not self.reading:
1144 return # Let the default binding (insert '\n') take over
1145 # If some text is selected, recall the selection
1146 # (but only if this before the I/O mark)
1147 try:
1148 sel = self.text.get("sel.first", "sel.last")
1149 if sel:
1150 if self.text.compare("sel.last", "<=", "iomark"):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001151 self.recall(sel, event)
David Scherer7aced172000-08-15 01:13:23 +00001152 return "break"
1153 except:
1154 pass
1155 # If we're strictly before the line containing iomark, recall
1156 # the current line, less a leading prompt, less leading or
1157 # trailing whitespace
1158 if self.text.compare("insert", "<", "iomark linestart"):
1159 # Check if there's a relevant stdin range -- if so, use it
1160 prev = self.text.tag_prevrange("stdin", "insert")
1161 if prev and self.text.compare("insert", "<", prev[1]):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001162 self.recall(self.text.get(prev[0], prev[1]), event)
David Scherer7aced172000-08-15 01:13:23 +00001163 return "break"
1164 next = self.text.tag_nextrange("stdin", "insert")
1165 if next and self.text.compare("insert lineend", ">=", next[0]):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001166 self.recall(self.text.get(next[0], next[1]), event)
David Scherer7aced172000-08-15 01:13:23 +00001167 return "break"
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001168 # No stdin mark -- just get the current line, less any prompt
Kurt B. Kaiserb1754452005-11-18 22:05:48 +00001169 indices = self.text.tag_nextrange("console", "insert linestart")
1170 if indices and \
1171 self.text.compare(indices[0], "<=", "insert linestart"):
1172 self.recall(self.text.get(indices[1], "insert lineend"), event)
1173 else:
1174 self.recall(self.text.get("insert linestart", "insert lineend"), event)
David Scherer7aced172000-08-15 01:13:23 +00001175 return "break"
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001176 # If we're between the beginning of the line and the iomark, i.e.
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001177 # in the prompt area, move to the end of the prompt
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001178 if self.text.compare("insert", "<", "iomark"):
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001179 self.text.mark_set("insert", "iomark")
David Scherer7aced172000-08-15 01:13:23 +00001180 # If we're in the current input and there's only whitespace
1181 # beyond the cursor, erase that whitespace first
1182 s = self.text.get("insert", "end-1c")
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001183 if s and not s.strip():
David Scherer7aced172000-08-15 01:13:23 +00001184 self.text.delete("insert", "end-1c")
1185 # If we're in the current input before its last line,
1186 # insert a newline right at the insert point
1187 if self.text.compare("insert", "<", "end-1c linestart"):
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001188 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001189 return "break"
1190 # We're in the last line; append a newline and submit it
1191 self.text.mark_set("insert", "end-1c")
1192 if self.reading:
1193 self.text.insert("insert", "\n")
1194 self.text.see("insert")
1195 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001196 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001197 self.text.tag_add("stdin", "iomark", "end-1c")
1198 self.text.update_idletasks()
1199 if self.reading:
1200 self.top.quit() # Break out of recursive mainloop() in raw_input()
1201 else:
1202 self.runit()
1203 return "break"
1204
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001205 def recall(self, s, event):
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001206 # remove leading and trailing empty or whitespace lines
1207 s = re.sub(r'^\s*\n', '' , s)
1208 s = re.sub(r'\n\s*$', '', s)
1209 lines = s.split('\n')
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001210 self.text.undo_block_start()
1211 try:
1212 self.text.tag_remove("sel", "1.0", "end")
1213 self.text.mark_set("insert", "end-1c")
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001214 prefix = self.text.get("insert linestart", "insert")
1215 if prefix.rstrip().endswith(':'):
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001216 self.newline_and_indent_event(event)
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001217 prefix = self.text.get("insert linestart", "insert")
1218 self.text.insert("insert", lines[0].strip())
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001219 if len(lines) > 1:
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001220 orig_base_indent = re.search(r'^([ \t]*)', lines[0]).group(0)
1221 new_base_indent = re.search(r'^([ \t]*)', prefix).group(0)
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001222 for line in lines[1:]:
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001223 if line.startswith(orig_base_indent):
1224 # replace orig base indentation with new indentation
1225 line = new_base_indent + line[len(orig_base_indent):]
1226 self.text.insert('insert', '\n'+line.rstrip())
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001227 finally:
1228 self.text.see("insert")
1229 self.text.undo_block_stop()
David Scherer7aced172000-08-15 01:13:23 +00001230
1231 def runit(self):
1232 line = self.text.get("iomark", "end-1c")
1233 # Strip off last newline and surrounding whitespace.
1234 # (To allow you to hit return twice to end a statement.)
1235 i = len(line)
1236 while i > 0 and line[i-1] in " \t":
1237 i = i-1
1238 if i > 0 and line[i-1] == "\n":
1239 i = i-1
1240 while i > 0 and line[i-1] in " \t":
1241 i = i-1
1242 line = line[:i]
1243 more = self.interp.runsource(line)
David Scherer7aced172000-08-15 01:13:23 +00001244
David Scherer7aced172000-08-15 01:13:23 +00001245 def open_stack_viewer(self, event=None):
Chui Tey5d2af632002-05-26 13:36:41 +00001246 if self.interp.rpcclt:
1247 return self.interp.remote_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +00001248 try:
1249 sys.last_traceback
1250 except:
1251 tkMessageBox.showerror("No stack trace",
1252 "There is no stack trace yet.\n"
1253 "(sys.last_traceback is not defined)",
1254 master=self.text)
1255 return
Florent Xiclunad630c042010-04-02 07:24:52 +00001256 from idlelib.StackViewer import StackBrowser
David Scherer7aced172000-08-15 01:13:23 +00001257 sv = StackBrowser(self.root, self.flist)
1258
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001259 def view_restart_mark(self, event=None):
1260 self.text.see("iomark")
1261 self.text.see("restart")
1262
1263 def restart_shell(self, event=None):
Terry Jan Reedyb98000a2012-01-31 02:09:25 -05001264 "Callback for Run/Restart Shell Cntl-F6"
1265 self.interp.restart_subprocess(with_cwd=True)
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001266
David Scherer7aced172000-08-15 01:13:23 +00001267 def showprompt(self):
1268 self.resetoutput()
1269 try:
1270 s = str(sys.ps1)
1271 except:
1272 s = ""
1273 self.console.write(s)
1274 self.text.mark_set("insert", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001275 self.set_line_and_column()
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +00001276 self.io.reset_undo()
David Scherer7aced172000-08-15 01:13:23 +00001277
1278 def resetoutput(self):
1279 source = self.text.get("iomark", "end-1c")
1280 if self.history:
Terry Jan Reedyb638a382013-08-13 19:51:04 -04001281 self.history.store(source)
David Scherer7aced172000-08-15 01:13:23 +00001282 if self.text.get("end-2c") != "\n":
1283 self.text.insert("end-1c", "\n")
1284 self.text.mark_set("iomark", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001285 self.set_line_and_column()
David Scherer7aced172000-08-15 01:13:23 +00001286 sys.stdout.softspace = 0
1287
1288 def write(self, s, tags=()):
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001289 try:
1290 self.text.mark_gravity("iomark", "right")
1291 OutputWindow.write(self, s, tags, "iomark")
1292 self.text.mark_gravity("iomark", "left")
1293 except:
1294 pass
David Scherer7aced172000-08-15 01:13:23 +00001295 if self.canceled:
1296 self.canceled = 0
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001297 if not use_subprocess:
1298 raise KeyboardInterrupt
David Scherer7aced172000-08-15 01:13:23 +00001299
Andrew Svetlov5018db72012-11-01 22:39:14 +02001300 def rmenu_check_cut(self):
1301 try:
1302 if self.text.compare('sel.first', '<', 'iomark'):
1303 return 'disabled'
1304 except TclError: # no selection, so the index 'sel.first' doesn't exist
1305 return 'disabled'
1306 return super(PyShell, self).rmenu_check_cut()
1307
1308 def rmenu_check_paste(self):
1309 if self.text.compare('insert', '<', 'iomark'):
1310 return 'disabled'
1311 return super(PyShell, self).rmenu_check_paste()
1312
Serhiy Storchaka9abc8302013-01-25 15:30:35 +02001313class PseudoFile(io.TextIOBase):
David Scherer7aced172000-08-15 01:13:23 +00001314
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001315 def __init__(self, shell, tags, encoding=None):
David Scherer7aced172000-08-15 01:13:23 +00001316 self.shell = shell
1317 self.tags = tags
Chui Tey5d2af632002-05-26 13:36:41 +00001318 self.softspace = 0
Serhiy Storchaka9abc8302013-01-25 15:30:35 +02001319 self._encoding = encoding
David Scherer7aced172000-08-15 01:13:23 +00001320
Serhiy Storchaka9abc8302013-01-25 15:30:35 +02001321 @property
1322 def encoding(self):
1323 return self._encoding
David Scherer7aced172000-08-15 01:13:23 +00001324
Serhiy Storchaka9abc8302013-01-25 15:30:35 +02001325 @property
1326 def name(self):
1327 return '<%s>' % self.tags
David Scherer7aced172000-08-15 01:13:23 +00001328
1329 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001330 return True
David Scherer7aced172000-08-15 01:13:23 +00001331
Serhiy Storchaka9abc8302013-01-25 15:30:35 +02001332
1333class PseudoOutputFile(PseudoFile):
1334
1335 def writable(self):
1336 return True
Martin v. Löwise2b56242012-07-25 10:56:22 +02001337
1338 def write(self, s):
Serhiy Storchaka9abc8302013-01-25 15:30:35 +02001339 if self.closed:
1340 raise ValueError("write to closed file")
Serhiy Storchaka7057f3f2013-12-10 10:04:41 +02001341 if type(s) not in (unicode, str, bytearray):
1342 # See issue #19481
1343 if isinstance(s, unicode):
1344 s = unicode.__getslice__(s, None, None)
1345 elif isinstance(s, str):
1346 s = str.__str__(s)
1347 elif isinstance(s, bytearray):
1348 s = bytearray.__str__(s)
1349 else:
1350 raise TypeError('must be string, not ' + type(s).__name__)
Serhiy Storchaka9abc8302013-01-25 15:30:35 +02001351 return self.shell.write(s, self.tags)
1352
1353
1354class PseudoInputFile(PseudoFile):
1355
1356 def __init__(self, shell, tags, encoding=None):
1357 PseudoFile.__init__(self, shell, tags, encoding)
1358 self._line_buffer = ''
1359
1360 def readable(self):
1361 return True
1362
1363 def read(self, size=-1):
1364 if self.closed:
1365 raise ValueError("read from closed file")
1366 if size is None:
1367 size = -1
1368 elif not isinstance(size, int):
1369 raise TypeError('must be int, not ' + type(size).__name__)
1370 result = self._line_buffer
1371 self._line_buffer = ''
1372 if size < 0:
1373 while True:
1374 line = self.shell.readline()
1375 if not line: break
1376 result += line
1377 else:
1378 while len(result) < size:
1379 line = self.shell.readline()
1380 if not line: break
1381 result += line
1382 self._line_buffer = result[size:]
1383 result = result[:size]
1384 return result
1385
1386 def readline(self, size=-1):
1387 if self.closed:
1388 raise ValueError("read from closed file")
1389 if size is None:
1390 size = -1
1391 elif not isinstance(size, int):
1392 raise TypeError('must be int, not ' + type(size).__name__)
1393 line = self._line_buffer or self.shell.readline()
1394 if size < 0:
1395 size = len(line)
Serhiy Storchaka0b6b3352013-12-25 14:24:17 +02001396 eol = line.find('\n', 0, size)
1397 if eol >= 0:
1398 size = eol + 1
Serhiy Storchaka9abc8302013-01-25 15:30:35 +02001399 self._line_buffer = line[size:]
1400 return line[:size]
Martin v. Löwise2b56242012-07-25 10:56:22 +02001401
Roger Serwy53dc4f02013-04-11 19:13:21 -05001402 def close(self):
1403 self.shell.close()
1404
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001405
David Scherer7aced172000-08-15 01:13:23 +00001406usage_msg = """\
David Scherer7aced172000-08-15 01:13:23 +00001407
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001408USAGE: idle [-deins] [-t title] [file]*
1409 idle [-dns] [-t title] (-c cmd | -r file) [arg]*
1410 idle [-dns] [-t title] - [arg]*
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001411
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001412 -h print this help message and exit
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001413 -n run IDLE without a subprocess (see Help/IDLE Help for details)
David Scherer7aced172000-08-15 01:13:23 +00001414
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001415The following options will override the IDLE 'settings' configuration:
Kurt B. Kaiser96d88422001-07-17 04:59:01 +00001416
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001417 -e open an edit window
1418 -i open a shell window
1419
1420The following options imply -i and will open a shell:
1421
1422 -c cmd run the command in a shell, or
1423 -r file run script from file
1424
1425 -d enable the debugger
1426 -s run $IDLESTARTUP or $PYTHONSTARTUP before anything else
1427 -t title set title of shell window
1428
1429A default edit window will be bypassed when -c, -r, or - are used.
1430
1431[arg]* are passed to the command (-c) or script (-r) in sys.argv[1:].
1432
1433Examples:
1434
1435idle
1436 Open an edit window or shell depending on IDLE's configuration.
1437
1438idle foo.py foobar.py
1439 Edit the files, also open a shell if configured to start with shell.
1440
1441idle -est "Baz" foo.py
1442 Run $IDLESTARTUP or $PYTHONSTARTUP, edit foo.py, and open a shell
1443 window with the title "Baz".
1444
1445idle -c "import sys; print sys.argv" "foo"
1446 Open a shell window and run the command, passing "-c" in sys.argv[0]
1447 and "foo" in sys.argv[1].
1448
1449idle -d -s -r foo.py "Hello World"
1450 Open a shell window, run a startup script, enable the debugger, and
1451 run foo.py, passing "foo.py" in sys.argv[0] and "Hello World" in
1452 sys.argv[1].
1453
1454echo "import sys; print sys.argv" | idle - "foobar"
1455 Open a shell window, run the script piped in, passing '' in sys.argv[0]
1456 and "foobar" in sys.argv[1].
David Scherer7aced172000-08-15 01:13:23 +00001457"""
1458
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001459def main():
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001460 global flist, root, use_subprocess
David Scherer7aced172000-08-15 01:13:23 +00001461
Terry Jan Reedy8eab0082013-06-28 23:51:34 -04001462 capture_warnings(True)
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001463 use_subprocess = True
Roger Serwy34d0c662013-03-31 23:28:55 -05001464 enable_shell = False
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001465 enable_edit = False
1466 debug = False
1467 cmd = None
1468 script = None
1469 startup = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001470 try:
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001471 opts, args = getopt.getopt(sys.argv[1:], "c:deihnr:st:")
Terry Jan Reedy2b149862013-06-29 00:59:34 -04001472 except getopt.error as msg:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001473 sys.stderr.write("Error: %s\n" % str(msg))
1474 sys.stderr.write(usage_msg)
1475 sys.exit(2)
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001476 for o, a in opts:
1477 if o == '-c':
1478 cmd = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001479 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001480 if o == '-d':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001481 debug = True
1482 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001483 if o == '-e':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001484 enable_edit = True
1485 if o == '-h':
1486 sys.stdout.write(usage_msg)
1487 sys.exit()
1488 if o == '-i':
1489 enable_shell = True
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001490 if o == '-n':
1491 use_subprocess = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001492 if o == '-r':
1493 script = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001494 if os.path.isfile(script):
1495 pass
1496 else:
1497 print "No script file: ", script
1498 sys.exit()
1499 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001500 if o == '-s':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001501 startup = True
1502 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001503 if o == '-t':
1504 PyShell.shell_title = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001505 enable_shell = True
1506 if args and args[0] == '-':
1507 cmd = sys.stdin.read()
1508 enable_shell = True
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001509 # process sys.argv and sys.path:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001510 for i in range(len(sys.path)):
1511 sys.path[i] = os.path.abspath(sys.path[i])
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001512 if args and args[0] == '-':
1513 sys.argv = [''] + args[1:]
1514 elif cmd:
1515 sys.argv = ['-c'] + args
1516 elif script:
1517 sys.argv = [script] + args
1518 elif args:
1519 enable_edit = True
1520 pathx = []
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001521 for filename in args:
1522 pathx.append(os.path.dirname(filename))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001523 for dir in pathx:
1524 dir = os.path.abspath(dir)
Florent Xiclunad630c042010-04-02 07:24:52 +00001525 if dir not in sys.path:
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001526 sys.path.insert(0, dir)
Kurt B. Kaiserff002b92002-12-21 21:39:11 +00001527 else:
1528 dir = os.getcwd()
1529 if not dir in sys.path:
1530 sys.path.insert(0, dir)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001531 # check the IDLE settings configuration (but command line overrides)
1532 edit_start = idleConf.GetOption('main', 'General',
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001533 'editor-on-startup', type='bool')
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001534 enable_edit = enable_edit or edit_start
Roger Serwy34d0c662013-03-31 23:28:55 -05001535 enable_shell = enable_shell or not enable_edit
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001536 # start editor and/or shell windows:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001537 root = Tk(className="Idle")
Ronald Oussoren19302d92006-06-11 14:33:36 +00001538
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001539 fixwordbreaks(root)
1540 root.withdraw()
1541 flist = PyShellFileList(root)
Ronald Oussoren19302d92006-06-11 14:33:36 +00001542 macosxSupport.setupApp(root, flist)
1543
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001544 if enable_edit:
1545 if not (cmd or script):
Andrew Svetlov7c010ee2012-03-21 13:35:08 +02001546 for filename in args[:]:
1547 if flist.open(filename) is None:
1548 # filename is a directory actually, disconsider it
1549 args.remove(filename)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001550 if not args:
1551 flist.new()
Ned Deily278543d2013-12-10 16:21:58 -08001552
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001553 if enable_shell:
Ronald Oussoren19302d92006-06-11 14:33:36 +00001554 shell = flist.open_shell()
1555 if not shell:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001556 return # couldn't open shell
Ronald Oussoren19302d92006-06-11 14:33:36 +00001557 if macosxSupport.runningAsOSXApp() and flist.dict:
1558 # On OSX: when the user has double-clicked on a file that causes
Tim Peters4f96f1f2006-06-11 19:42:51 +00001559 # IDLE to be launched the shell window will open just in front of
1560 # the file she wants to see. Lower the interpreter window when
Ronald Oussoren19302d92006-06-11 14:33:36 +00001561 # there are open files.
1562 shell.top.lower()
Ned Deily278543d2013-12-10 16:21:58 -08001563 else:
1564 shell = flist.pyshell
Ronald Oussoren19302d92006-06-11 14:33:36 +00001565
Ned Deily278543d2013-12-10 16:21:58 -08001566 # Handle remaining options. If any of these are set, enable_shell
1567 # was set also, so shell must be true to reach here.
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001568 if debug:
1569 shell.open_debugger()
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001570 if startup:
1571 filename = os.environ.get("IDLESTARTUP") or \
1572 os.environ.get("PYTHONSTARTUP")
1573 if filename and os.path.isfile(filename):
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001574 shell.interp.execfile(filename)
Ned Deily278543d2013-12-10 16:21:58 -08001575 if cmd or script:
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001576 shell.interp.runcommand("""if 1:
1577 import sys as _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001578 _sys.argv = %r
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001579 del _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001580 \n""" % (sys.argv,))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001581 if cmd:
1582 shell.interp.execsource(cmd)
1583 elif script:
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001584 shell.interp.prepend_syspath(script)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001585 shell.interp.execfile(script)
Ned Deily278543d2013-12-10 16:21:58 -08001586 elif shell:
1587 # If there is a shell window and no cmd or script in progress,
1588 # check for problematic OS X Tk versions and print a warning
1589 # message in the IDLE shell window; this is less intrusive
1590 # than always opening a separate window.
1591 tkversionwarning = macosxSupport.tkVersionWarning(root)
1592 if tkversionwarning:
1593 shell.interp.runcommand("print('%s')" % tkversionwarning)
Ned Deily2a6f4b32011-01-30 00:18:47 +00001594
Terry Jan Reedyeaa7e782012-05-26 20:33:32 -04001595 while flist.inversedict: # keep IDLE running while files are open.
1596 root.mainloop()
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001597 root.destroy()
Terry Jan Reedy8eab0082013-06-28 23:51:34 -04001598 capture_warnings(False)
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001599
David Scherer7aced172000-08-15 01:13:23 +00001600if __name__ == "__main__":
Kurt B. Kaiser9e8b8282003-06-15 17:38:45 +00001601 sys.modules['PyShell'] = sys.modules['__main__']
David Scherer7aced172000-08-15 01:13:23 +00001602 main()
Terry Jan Reedy8eab0082013-06-28 23:51:34 -04001603
1604capture_warnings(False) # Make sure turned off; see issue 18081