blob: 278f4f658b11ad5936214029a923861f22c4bb04 [file] [log] [blame]
Benjamin Peterson90f5ba52010-03-11 22:53:45 +00001#! /usr/bin/env python3
David Scherer7aced172000-08-15 01:13:23 +00002
Victor Stinner979482a2011-09-02 01:00:40 +02003import getopt
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 re
Chui Tey5d2af632002-05-26 13:36:41 +00007import socket
Victor Stinner979482a2011-09-02 01:00:40 +02008import subprocess
9import sys
Kurt B. Kaiser003091c2003-02-17 18:57:16 +000010import threading
Victor Stinner979482a2011-09-02 01:00:40 +020011import time
12import tokenize
Chui Tey5d2af632002-05-26 13:36:41 +000013import traceback
Kurt B. Kaiser62833982002-09-18 17:07:05 +000014import types
David Scherer7aced172000-08-15 01:13:23 +000015
16import linecache
17from code import InteractiveInterpreter
18
Kurt B. Kaiser2303b1c2003-11-24 05:26:16 +000019try:
Georg Brandl14fc4272008-05-17 18:39:55 +000020 from tkinter import *
Kurt B. Kaiser2303b1c2003-11-24 05:26:16 +000021except ImportError:
Guido van Rossumbe19ed72007-02-09 05:37:30 +000022 print("** IDLE can't import Tkinter. " \
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +000023 "Your Python may not be configured for Tk. **", file=sys.__stderr__)
Kurt B. Kaiser2303b1c2003-11-24 05:26:16 +000024 sys.exit(1)
Georg Brandl14fc4272008-05-17 18:39:55 +000025import tkinter.messagebox as tkMessageBox
David Scherer7aced172000-08-15 01:13:23 +000026
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +000027from idlelib.EditorWindow import EditorWindow, fixwordbreaks
28from idlelib.FileList import FileList
29from idlelib.ColorDelegator import ColorDelegator
30from idlelib.UndoDelegator import UndoDelegator
31from idlelib.OutputWindow import OutputWindow
32from idlelib.configHandler import idleConf
33from idlelib import idlever
34from idlelib import rpc
35from idlelib import Debugger
36from idlelib import RemoteDebugger
37from idlelib import macosxSupport
Chui Tey5d2af632002-05-26 13:36:41 +000038
Kurt B. Kaisere866c812009-04-04 21:07:39 +000039HOST = '127.0.0.1' # python execution server on localhost loopback
40PORT = 0 # someday pass in host, port for remote debug capability
Kurt B. Kaiserb9764192002-09-23 04:10:37 +000041
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000042# Override warnings module to write to warning_stream. Initialize to send IDLE
43# internal warnings to the console. ScriptBinding.check_syntax() will
44# temporarily redirect the stream to the shell window to display warnings when
45# checking user's code.
46global warning_stream
47warning_stream = sys.__stderr__
Chui Tey5d2af632002-05-26 13:36:41 +000048try:
49 import warnings
50except ImportError:
51 pass
52else:
Benjamin Peterson206e3072008-10-19 14:07:49 +000053 def idle_showwarning(message, category, filename, lineno,
54 file=None, line=None):
Guilherme Polo1fff0082009-08-14 15:05:30 +000055 if file is None:
56 file = warning_stream
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000057 try:
Guilherme Polo1fff0082009-08-14 15:05:30 +000058 file.write(warnings.formatwarning(message, category, filename,
Senthil Kumaranaa90e7c2011-07-03 17:39:20 -070059 lineno, line=line))
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000060 except IOError:
61 pass ## file (probably __stderr__) is invalid, warning dropped.
Chui Tey5d2af632002-05-26 13:36:41 +000062 warnings.showwarning = idle_showwarning
Guilherme Polo1fff0082009-08-14 15:05:30 +000063 def idle_formatwarning(message, category, filename, lineno, line=None):
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000064 """Format warnings the IDLE way"""
65 s = "\nWarning (from warnings module):\n"
66 s += ' File \"%s\", line %s\n' % (filename, lineno)
Guilherme Polo1fff0082009-08-14 15:05:30 +000067 if line is None:
68 line = linecache.getline(filename, lineno)
69 line = line.strip()
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000070 if line:
71 s += " %s\n" % line
72 s += "%s: %s\n>>> " % (category.__name__, message)
73 return s
74 warnings.formatwarning = idle_formatwarning
Chui Tey5d2af632002-05-26 13:36:41 +000075
Kurt B. Kaiserf7a88992004-11-13 21:05:58 +000076def extended_linecache_checkcache(filename=None,
77 orig_checkcache=linecache.checkcache):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +000078 """Extend linecache.checkcache to preserve the <pyshell#...> entries
79
Kurt B. Kaiserf7a88992004-11-13 21:05:58 +000080 Rather than repeating the linecache code, patch it to save the
81 <pyshell#...> entries, call the original linecache.checkcache()
Guilherme Polo1fff0082009-08-14 15:05:30 +000082 (skipping them), and then restore the saved entries.
Kurt B. Kaiserf7a88992004-11-13 21:05:58 +000083
84 orig_checkcache is bound at definition time to the original
85 method, allowing it to be patched.
Kurt B. Kaiser45186c42002-10-23 04:48:08 +000086 """
David Scherer7aced172000-08-15 01:13:23 +000087 cache = linecache.cache
88 save = {}
Guilherme Polo1fff0082009-08-14 15:05:30 +000089 for key in list(cache):
90 if key[:1] + key[-1:] == '<>':
91 save[key] = cache.pop(key)
92 orig_checkcache(filename)
David Scherer7aced172000-08-15 01:13:23 +000093 cache.update(save)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +000094
Kurt B. Kaiser81885592002-11-29 22:10:53 +000095# Patch linecache.checkcache():
96linecache.checkcache = extended_linecache_checkcache
David Scherer7aced172000-08-15 01:13:23 +000097
Kurt B. Kaiser45186c42002-10-23 04:48:08 +000098
David Scherer7aced172000-08-15 01:13:23 +000099class PyShellEditorWindow(EditorWindow):
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000100 "Regular text edit window in IDLE, supports breakpoints"
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000101
David Scherer7aced172000-08-15 01:13:23 +0000102 def __init__(self, *args):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000103 self.breakpoints = []
Raymond Hettinger931237e2003-07-09 18:48:24 +0000104 EditorWindow.__init__(self, *args)
David Scherer7aced172000-08-15 01:13:23 +0000105 self.text.bind("<<set-breakpoint-here>>", self.set_breakpoint_here)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000106 self.text.bind("<<clear-breakpoint-here>>", self.clear_breakpoint_here)
David Scherer7aced172000-08-15 01:13:23 +0000107 self.text.bind("<<open-python-shell>>", self.flist.open_shell)
108
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000109 self.breakpointPath = os.path.join(idleConf.GetUserCfgDir(),
110 'breakpoints.lst')
Chui Teya2adb0f2002-11-04 22:14:54 +0000111 # whenever a file is changed, restore breakpoints
112 if self.io.filename: self.restore_file_breaks()
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000113 def filename_changed_hook(old_hook=self.io.filename_change_hook,
114 self=self):
Chui Teya2adb0f2002-11-04 22:14:54 +0000115 self.restore_file_breaks()
116 old_hook()
117 self.io.set_filename_change_hook(filename_changed_hook)
118
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000119 rmenu_specs = [("Set Breakpoint", "<<set-breakpoint-here>>"),
120 ("Clear Breakpoint", "<<clear-breakpoint-here>>")]
David Scherer7aced172000-08-15 01:13:23 +0000121
Chui Teya2adb0f2002-11-04 22:14:54 +0000122 def set_breakpoint(self, lineno):
123 text = self.text
124 filename = self.io.filename
125 text.tag_add("BREAK", "%d.0" % lineno, "%d.0" % (lineno+1))
126 try:
127 i = self.breakpoints.index(lineno)
128 except ValueError: # only add if missing, i.e. do once
129 self.breakpoints.append(lineno)
130 try: # update the subprocess debugger
131 debug = self.flist.pyshell.interp.debugger
132 debug.set_breakpoint_here(filename, lineno)
133 except: # but debugger may not be active right now....
134 pass
135
David Scherer7aced172000-08-15 01:13:23 +0000136 def set_breakpoint_here(self, event=None):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000137 text = self.text
138 filename = self.io.filename
139 if not filename:
140 text.bell()
David Scherer7aced172000-08-15 01:13:23 +0000141 return
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000142 lineno = int(float(text.index("insert")))
Chui Teya2adb0f2002-11-04 22:14:54 +0000143 self.set_breakpoint(lineno)
David Scherer7aced172000-08-15 01:13:23 +0000144
Kurt B. Kaiser669f4c32002-06-20 04:01:47 +0000145 def clear_breakpoint_here(self, event=None):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000146 text = self.text
147 filename = self.io.filename
148 if not filename:
149 text.bell()
Kurt B. Kaiser669f4c32002-06-20 04:01:47 +0000150 return
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000151 lineno = int(float(text.index("insert")))
152 try:
153 self.breakpoints.remove(lineno)
154 except:
155 pass
156 text.tag_remove("BREAK", "insert linestart",\
157 "insert lineend +1char")
158 try:
159 debug = self.flist.pyshell.interp.debugger
160 debug.clear_breakpoint_here(filename, lineno)
161 except:
162 pass
163
164 def clear_file_breaks(self):
165 if self.breakpoints:
166 text = self.text
167 filename = self.io.filename
168 if not filename:
169 text.bell()
170 return
171 self.breakpoints = []
172 text.tag_remove("BREAK", "1.0", END)
173 try:
174 debug = self.flist.pyshell.interp.debugger
175 debug.clear_file_breaks(filename)
176 except:
177 pass
178
Chui Teya2adb0f2002-11-04 22:14:54 +0000179 def store_file_breaks(self):
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000180 "Save breakpoints when file is saved"
181 # XXX 13 Dec 2002 KBK Currently the file must be saved before it can
182 # be run. The breaks are saved at that time. If we introduce
183 # a temporary file save feature the save breaks functionality
184 # needs to be re-verified, since the breaks at the time the
185 # temp file is created may differ from the breaks at the last
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000186 # permanent save of the file. Currently, a break introduced
187 # after a save will be effective, but not persistent.
188 # This is necessary to keep the saved breaks synched with the
189 # saved file.
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000190 #
191 # Breakpoints are set as tagged ranges in the text. Certain
192 # kinds of edits cause these ranges to be deleted: Inserting
193 # or deleting a line just before a breakpoint, and certain
194 # deletions prior to a breakpoint. These issues need to be
195 # investigated and understood. It's not clear if they are
196 # Tk issues or IDLE issues, or whether they can actually
197 # be fixed. Since a modified file has to be saved before it is
198 # run, and since self.breakpoints (from which the subprocess
199 # debugger is loaded) is updated during the save, the visible
200 # breaks stay synched with the subprocess even if one of these
201 # unexpected breakpoint deletions occurs.
202 breaks = self.breakpoints
203 filename = self.io.filename
Chui Teya2adb0f2002-11-04 22:14:54 +0000204 try:
Victor Stinner85c67722011-09-02 00:57:04 +0200205 with open(self.breakpointPath, "r") as fp:
206 lines = fp.readlines()
Chui Teya2adb0f2002-11-04 22:14:54 +0000207 except IOError:
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000208 lines = []
Ned Deilyf505b742011-12-14 14:58:24 -0800209 try:
210 with open(self.breakpointPath, "w") as new_file:
211 for line in lines:
212 if not line.startswith(filename + '='):
213 new_file.write(line)
214 self.update_breakpoints()
215 breaks = self.breakpoints
216 if breaks:
217 new_file.write(filename + '=' + str(breaks) + '\n')
218 except IOError as err:
219 if not getattr(self.root, "breakpoint_error_displayed", False):
220 self.root.breakpoint_error_displayed = True
221 tkMessageBox.showerror(title='IDLE Error',
222 message='Unable to update breakpoint list:\n%s'
223 % str(err),
224 parent=self.text)
Chui Teya2adb0f2002-11-04 22:14:54 +0000225
226 def restore_file_breaks(self):
227 self.text.update() # this enables setting "BREAK" tags to be visible
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000228 filename = self.io.filename
229 if filename is None:
230 return
Chui Tey69371d62002-11-04 23:39:45 +0000231 if os.path.isfile(self.breakpointPath):
Victor Stinner85c67722011-09-02 00:57:04 +0200232 with open(self.breakpointPath, "r") as fp:
233 lines = fp.readlines()
Chui Tey69371d62002-11-04 23:39:45 +0000234 for line in lines:
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000235 if line.startswith(filename + '='):
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000236 breakpoint_linenumbers = eval(line[len(filename)+1:])
Chui Tey69371d62002-11-04 23:39:45 +0000237 for breakpoint_linenumber in breakpoint_linenumbers:
238 self.set_breakpoint(breakpoint_linenumber)
Chui Teya2adb0f2002-11-04 22:14:54 +0000239
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000240 def update_breakpoints(self):
241 "Retrieves all the breakpoints in the current window"
Chui Teya2adb0f2002-11-04 22:14:54 +0000242 text = self.text
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000243 ranges = text.tag_ranges("BREAK")
244 linenumber_list = self.ranges_to_linenumbers(ranges)
245 self.breakpoints = linenumber_list
246
247 def ranges_to_linenumbers(self, ranges):
248 lines = []
249 for index in range(0, len(ranges), 2):
250 lineno = int(float(ranges[index]))
251 end = int(float(ranges[index+1]))
252 while lineno < end:
253 lines.append(lineno)
254 lineno += 1
255 return lines
256
Kurt B. Kaiser11220fa2002-12-24 00:57:22 +0000257# XXX 13 Dec 2002 KBK Not used currently
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000258# def saved_change_hook(self):
259# "Extend base method - clear breaks if module is modified"
260# if not self.get_saved():
261# self.clear_file_breaks()
262# EditorWindow.saved_change_hook(self)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000263
264 def _close(self):
265 "Extend base method - clear breaks when module is closed"
266 self.clear_file_breaks()
267 EditorWindow._close(self)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000268
David Scherer7aced172000-08-15 01:13:23 +0000269
270class PyShellFileList(FileList):
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000271 "Extend base class: IDLE supports a shell and breakpoints"
David Scherer7aced172000-08-15 01:13:23 +0000272
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000273 # override FileList's class variable, instances return PyShellEditorWindow
274 # instead of EditorWindow when new edit windows are created.
David Scherer7aced172000-08-15 01:13:23 +0000275 EditorWindow = PyShellEditorWindow
276
277 pyshell = None
278
279 def open_shell(self, event=None):
280 if self.pyshell:
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000281 self.pyshell.top.wakeup()
David Scherer7aced172000-08-15 01:13:23 +0000282 else:
283 self.pyshell = PyShell(self)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000284 if self.pyshell:
285 if not self.pyshell.begin():
286 return None
David Scherer7aced172000-08-15 01:13:23 +0000287 return self.pyshell
288
289
290class ModifiedColorDelegator(ColorDelegator):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000291 "Extend base class: colorizer for the shell window itself"
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000292
Steven M. Gavab77d3432002-03-02 07:16:21 +0000293 def __init__(self):
294 ColorDelegator.__init__(self)
295 self.LoadTagDefs()
David Scherer7aced172000-08-15 01:13:23 +0000296
297 def recolorize_main(self):
298 self.tag_remove("TODO", "1.0", "iomark")
299 self.tag_add("SYNC", "1.0", "iomark")
300 ColorDelegator.recolorize_main(self)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000301
Steven M. Gavab77d3432002-03-02 07:16:21 +0000302 def LoadTagDefs(self):
303 ColorDelegator.LoadTagDefs(self)
304 theme = idleConf.GetOption('main','Theme','name')
305 self.tagdefs.update({
306 "stdin": {'background':None,'foreground':None},
307 "stdout": idleConf.GetHighlight(theme, "stdout"),
308 "stderr": idleConf.GetHighlight(theme, "stderr"),
309 "console": idleConf.GetHighlight(theme, "console"),
Steven M. Gavab77d3432002-03-02 07:16:21 +0000310 })
David Scherer7aced172000-08-15 01:13:23 +0000311
Ned Deily8b2a56b2012-05-31 09:17:29 -0700312 def removecolors(self):
313 # Don't remove shell color tags before "iomark"
314 for tag in self.tagdefs:
315 self.tag_remove(tag, "iomark", "end")
316
David Scherer7aced172000-08-15 01:13:23 +0000317class ModifiedUndoDelegator(UndoDelegator):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000318 "Extend base class: forbid insert/delete before the I/O mark"
David Scherer7aced172000-08-15 01:13:23 +0000319
320 def insert(self, index, chars, tags=None):
321 try:
322 if self.delegate.compare(index, "<", "iomark"):
323 self.delegate.bell()
324 return
325 except TclError:
326 pass
327 UndoDelegator.insert(self, index, chars, tags)
328
329 def delete(self, index1, index2=None):
330 try:
331 if self.delegate.compare(index1, "<", "iomark"):
332 self.delegate.bell()
333 return
334 except TclError:
335 pass
336 UndoDelegator.delete(self, index1, index2)
337
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000338
339class MyRPCClient(rpc.RPCClient):
340
341 def handle_EOF(self):
342 "Override the base class - just re-raise EOFError"
343 raise EOFError
344
Kurt B. Kaiser8d1f11b2003-05-26 22:20:34 +0000345
David Scherer7aced172000-08-15 01:13:23 +0000346class ModifiedInterpreter(InteractiveInterpreter):
347
348 def __init__(self, tkconsole):
349 self.tkconsole = tkconsole
350 locals = sys.modules['__main__'].__dict__
351 InteractiveInterpreter.__init__(self, locals=locals)
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000352 self.save_warnings_filters = None
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000353 self.restarting = False
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000354 self.subprocess_arglist = None
355 self.port = PORT
Ned Deily7aff4512011-10-30 20:01:35 -0700356 self.original_compiler_flags = self.compile.compiler.flags
David Scherer7aced172000-08-15 01:13:23 +0000357
Chui Tey5d2af632002-05-26 13:36:41 +0000358 rpcclt = None
Ned Deilye5cad232011-08-02 18:47:13 -0700359 rpcsubproc = None
Chui Tey5d2af632002-05-26 13:36:41 +0000360
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000361 def spawn_subprocess(self):
Florent Xiclunafd1b0932010-03-28 00:25:02 +0000362 if self.subprocess_arglist is None:
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000363 self.subprocess_arglist = self.build_subprocess_arglist()
Ned Deilye5cad232011-08-02 18:47:13 -0700364 self.rpcsubproc = subprocess.Popen(self.subprocess_arglist)
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000365
Tony Lowndsf53dec22002-12-20 04:24:43 +0000366 def build_subprocess_arglist(self):
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000367 assert (self.port!=0), (
368 "Socket should have been assigned a port number.")
Tony Lownds2398d572003-05-13 15:28:21 +0000369 w = ['-W' + s for s in sys.warnoptions]
370 # Maybe IDLE is installed and is being accessed via sys.path,
371 # or maybe it's not installed and the idle.py script is being
372 # run from the IDLE source directory.
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000373 del_exitf = idleConf.GetOption('main', 'General', 'delete-exitfunc',
374 default=False, type='bool')
Tony Lownds2398d572003-05-13 15:28:21 +0000375 if __name__ == 'idlelib.PyShell':
Walter Dörwald70a6b492004-02-12 17:35:32 +0000376 command = "__import__('idlelib.run').run.main(%r)" % (del_exitf,)
Tony Lowndsf2324b92002-09-29 00:34:10 +0000377 else:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000378 command = "__import__('run').main(%r)" % (del_exitf,)
Ned Deilye5cad232011-08-02 18:47:13 -0700379 return [sys.executable] + w + ["-c", command, str(self.port)]
Tony Lowndsf2324b92002-09-29 00:34:10 +0000380
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000381 def start_subprocess(self):
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000382 addr = (HOST, self.port)
383 # GUI makes several attempts to acquire socket, listens for connection
Kurt B. Kaiser5db48432003-05-15 03:40:51 +0000384 for i in range(3):
Chui Tey5d2af632002-05-26 13:36:41 +0000385 time.sleep(i)
386 try:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000387 self.rpcclt = MyRPCClient(addr)
Chui Tey5d2af632002-05-26 13:36:41 +0000388 break
Guido van Rossumb940e112007-01-10 16:19:56 +0000389 except socket.error as err:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000390 pass
Chui Tey5d2af632002-05-26 13:36:41 +0000391 else:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000392 self.display_port_binding_error()
393 return None
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000394 # if PORT was 0, system will assign an 'ephemeral' port. Find it out:
395 self.port = self.rpcclt.listening_sock.getsockname()[1]
396 # if PORT was not 0, probably working with a remote execution server
397 if PORT != 0:
398 # To allow reconnection within the 2MSL wait (cf. Stevens TCP
399 # V1, 18.6), set SO_REUSEADDR. Note that this can be problematic
400 # on Windows since the implementation allows two active sockets on
401 # the same address!
402 self.rpcclt.listening_sock.setsockopt(socket.SOL_SOCKET,
403 socket.SO_REUSEADDR, 1)
404 self.spawn_subprocess()
405 #time.sleep(20) # test to simulate GUI not accepting connection
Kurt B. Kaiserb4179362002-07-26 00:06:42 +0000406 # Accept the connection from the Python execution server
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000407 self.rpcclt.listening_sock.settimeout(10)
408 try:
409 self.rpcclt.accept()
Guido van Rossumb940e112007-01-10 16:19:56 +0000410 except socket.timeout as err:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000411 self.display_no_subprocess_error()
412 return None
Kurt B. Kaiser969de452002-06-12 03:28:57 +0000413 self.rpcclt.register("stdin", self.tkconsole)
414 self.rpcclt.register("stdout", self.tkconsole.stdout)
415 self.rpcclt.register("stderr", self.tkconsole.stderr)
Chui Tey5d2af632002-05-26 13:36:41 +0000416 self.rpcclt.register("flist", self.tkconsole.flist)
Kurt B. Kaiser8cd0def2003-01-31 05:06:43 +0000417 self.rpcclt.register("linecache", linecache)
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000418 self.rpcclt.register("interp", self)
Terry Jan Reedyda4c4672012-01-31 02:26:32 -0500419 self.transfer_path(with_cwd=True)
Chui Tey5d2af632002-05-26 13:36:41 +0000420 self.poll_subprocess()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000421 return self.rpcclt
Chui Tey5d2af632002-05-26 13:36:41 +0000422
Terry Jan Reedyda4c4672012-01-31 02:26:32 -0500423 def restart_subprocess(self, with_cwd=False):
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000424 if self.restarting:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000425 return self.rpcclt
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000426 self.restarting = True
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000427 # close only the subprocess debugger
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000428 debug = self.getdebugger()
429 if debug:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000430 try:
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000431 # Only close subprocess debugger, don't unregister gui_adap!
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000432 RemoteDebugger.close_subprocess_debugger(self.rpcclt)
433 except:
434 pass
435 # Kill subprocess, spawn a new one, accept connection.
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000436 self.rpcclt.close()
Ned Deilye5cad232011-08-02 18:47:13 -0700437 self.terminate_subprocess()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000438 console = self.tkconsole
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000439 was_executing = console.executing
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000440 console.executing = False
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000441 self.spawn_subprocess()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000442 try:
443 self.rpcclt.accept()
Guido van Rossumb940e112007-01-10 16:19:56 +0000444 except socket.timeout as err:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000445 self.display_no_subprocess_error()
446 return None
Terry Jan Reedyda4c4672012-01-31 02:26:32 -0500447 self.transfer_path(with_cwd=with_cwd)
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000448 # annotate restart in shell window and mark it
Kurt B. Kaiser4cc5ef52003-01-22 00:23:23 +0000449 console.text.delete("iomark", "end-1c")
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000450 if was_executing:
451 console.write('\n')
452 console.showprompt()
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000453 halfbar = ((int(console.width) - 16) // 2) * '='
454 console.write(halfbar + ' RESTART ' + halfbar)
455 console.text.mark_set("restart", "end-1c")
456 console.text.mark_gravity("restart", "left")
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000457 console.showprompt()
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000458 # restart subprocess debugger
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000459 if debug:
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000460 # Restarted debugger connects to current instance of debug GUI
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000461 gui = RemoteDebugger.restart_subprocess_debugger(self.rpcclt)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000462 # reload remote debugger breakpoints for all PyShellEditWindows
463 debug.load_breakpoints()
Ned Deily7aff4512011-10-30 20:01:35 -0700464 self.compile.compiler.flags = self.original_compiler_flags
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000465 self.restarting = False
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000466 return self.rpcclt
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000467
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000468 def __request_interrupt(self):
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000469 self.rpcclt.remotecall("exec", "interrupt_the_server", (), {})
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000470
471 def interrupt_subprocess(self):
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000472 threading.Thread(target=self.__request_interrupt).start()
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000473
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000474 def kill_subprocess(self):
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000475 try:
476 self.rpcclt.close()
477 except AttributeError: # no socket
478 pass
Ned Deilye5cad232011-08-02 18:47:13 -0700479 self.terminate_subprocess()
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000480 self.tkconsole.executing = False
481 self.rpcclt = None
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000482
Ned Deilye5cad232011-08-02 18:47:13 -0700483 def terminate_subprocess(self):
484 "Make sure subprocess is terminated"
485 try:
486 self.rpcsubproc.kill()
487 except OSError:
488 # process already terminated
489 return
490 else:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000491 try:
Ned Deilye5cad232011-08-02 18:47:13 -0700492 self.rpcsubproc.wait()
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000493 except OSError:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000494 return
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000495
Terry Jan Reedyda4c4672012-01-31 02:26:32 -0500496 def transfer_path(self, with_cwd=False):
497 if with_cwd: # Issue 13506
498 path = [''] # include Current Working Directory
499 path.extend(sys.path)
500 else:
501 path = sys.path
Terry Jan Reedy4d82ade2012-01-31 02:57:29 -0500502
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000503 self.runcommand("""if 1:
504 import sys as _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +0000505 _sys.path = %r
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000506 del _sys
Terry Jan Reedyda4c4672012-01-31 02:26:32 -0500507 \n""" % (path,))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000508
Chui Tey5d2af632002-05-26 13:36:41 +0000509 active_seq = None
510
511 def poll_subprocess(self):
512 clt = self.rpcclt
513 if clt is None:
514 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000515 try:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000516 response = clt.pollresponse(self.active_seq, wait=0.05)
517 except (EOFError, IOError, KeyboardInterrupt):
518 # lost connection or subprocess terminated itself, restart
519 # [the KBI is from rpc.SocketIO.handle_EOF()]
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000520 if self.tkconsole.closing:
521 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000522 response = None
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000523 self.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000524 if response:
525 self.tkconsole.resetoutput()
526 self.active_seq = None
527 how, what = response
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000528 console = self.tkconsole.console
Chui Tey5d2af632002-05-26 13:36:41 +0000529 if how == "OK":
530 if what is not None:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000531 print(repr(what), file=console)
Chui Tey5d2af632002-05-26 13:36:41 +0000532 elif how == "EXCEPTION":
Chui Tey5d2af632002-05-26 13:36:41 +0000533 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
534 self.remote_stack_viewer()
535 elif how == "ERROR":
Kurt B. Kaiser0930c432002-12-06 21:45:24 +0000536 errmsg = "PyShell.ModifiedInterpreter: Subprocess ERROR:\n"
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000537 print(errmsg, what, file=sys.__stderr__)
538 print(errmsg, what, file=console)
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000539 # we received a response to the currently active seq number:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000540 try:
541 self.tkconsole.endexecuting()
542 except AttributeError: # shell may have closed
543 pass
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000544 # Reschedule myself
545 if not self.tkconsole.closing:
546 self.tkconsole.text.after(self.tkconsole.pollinterval,
547 self.poll_subprocess)
Chui Tey5d2af632002-05-26 13:36:41 +0000548
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000549 debugger = None
550
551 def setdebugger(self, debugger):
552 self.debugger = debugger
553
554 def getdebugger(self):
555 return self.debugger
556
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000557 def open_remote_stack_viewer(self):
558 """Initiate the remote stack viewer from a separate thread.
559
560 This method is called from the subprocess, and by returning from this
561 method we allow the subprocess to unblock. After a bit the shell
562 requests the subprocess to open the remote stack viewer which returns a
Ezio Melotti60861182010-07-23 16:48:22 +0000563 static object looking at the last exception. It is queried through
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000564 the RPC mechanism.
565
566 """
567 self.tkconsole.text.after(300, self.remote_stack_viewer)
568 return
569
Chui Tey5d2af632002-05-26 13:36:41 +0000570 def remote_stack_viewer(self):
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000571 from idlelib import RemoteObjectBrowser
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000572 oid = self.rpcclt.remotequeue("exec", "stackviewer", ("flist",), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000573 if oid is None:
574 self.tkconsole.root.bell()
575 return
576 item = RemoteObjectBrowser.StubObjectTreeItem(self.rpcclt, oid)
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000577 from idlelib.TreeWidget import ScrolledCanvas, TreeNode
Chui Tey5d2af632002-05-26 13:36:41 +0000578 top = Toplevel(self.tkconsole.root)
Kurt B. Kaiser73360a32004-03-08 18:15:31 +0000579 theme = idleConf.GetOption('main','Theme','name')
580 background = idleConf.GetHighlight(theme, 'normal')['background']
581 sc = ScrolledCanvas(top, bg=background, highlightthickness=0)
Chui Tey5d2af632002-05-26 13:36:41 +0000582 sc.frame.pack(expand=1, fill="both")
583 node = TreeNode(sc.canvas, None, item)
584 node.expand()
585 # XXX Should GC the remote tree when closing the window
586
David Scherer7aced172000-08-15 01:13:23 +0000587 gid = 0
588
589 def execsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000590 "Like runsource() but assumes complete exec source"
David Scherer7aced172000-08-15 01:13:23 +0000591 filename = self.stuffsource(source)
592 self.execfile(filename, source)
593
594 def execfile(self, filename, source=None):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000595 "Execute an existing file"
David Scherer7aced172000-08-15 01:13:23 +0000596 if source is None:
Victor Stinner979482a2011-09-02 01:00:40 +0200597 with tokenize.open(filename) as fp:
Victor Stinner85c67722011-09-02 00:57:04 +0200598 source = fp.read()
David Scherer7aced172000-08-15 01:13:23 +0000599 try:
600 code = compile(source, filename, "exec")
601 except (OverflowError, SyntaxError):
602 self.tkconsole.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000603 tkerr = self.tkconsole.stderr
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000604 print('*** Error in script or command!\n', file=tkerr)
605 print('Traceback (most recent call last):', file=tkerr)
David Scherer7aced172000-08-15 01:13:23 +0000606 InteractiveInterpreter.showsyntaxerror(self, filename)
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000607 self.tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000608 else:
609 self.runcode(code)
610
611 def runsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000612 "Extend base class method: Stuff the source in the line cache first"
David Scherer7aced172000-08-15 01:13:23 +0000613 filename = self.stuffsource(source)
614 self.more = 0
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000615 self.save_warnings_filters = warnings.filters[:]
616 warnings.filterwarnings(action="error", category=SyntaxWarning)
Martin v. Löwis98ff8982007-08-13 06:03:15 +0000617 # at the moment, InteractiveInterpreter expects str
618 assert isinstance(source, str)
619 #if isinstance(source, str):
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000620 # from idlelib import IOBinding
Martin v. Löwis98ff8982007-08-13 06:03:15 +0000621 # try:
622 # source = source.encode(IOBinding.encoding)
623 # except UnicodeError:
624 # self.tkconsole.resetoutput()
625 # self.write("Unsupported characters in input\n")
626 # return
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000627 try:
Kurt B. Kaiser935ea9a2005-05-10 03:44:24 +0000628 # InteractiveInterpreter.runsource() calls its runcode() method,
629 # which is overridden (see below)
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000630 return InteractiveInterpreter.runsource(self, source, filename)
631 finally:
632 if self.save_warnings_filters is not None:
633 warnings.filters[:] = self.save_warnings_filters
634 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000635
636 def stuffsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000637 "Stuff source in the filename cache"
David Scherer7aced172000-08-15 01:13:23 +0000638 filename = "<pyshell#%d>" % self.gid
639 self.gid = self.gid + 1
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000640 lines = source.split("\n")
David Scherer7aced172000-08-15 01:13:23 +0000641 linecache.cache[filename] = len(source)+1, 0, lines, filename
642 return filename
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000643
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000644 def prepend_syspath(self, filename):
645 "Prepend sys.path with file's directory if not already included"
646 self.runcommand("""if 1:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000647 _filename = %r
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000648 import sys as _sys
649 from os.path import dirname as _dirname
650 _dir = _dirname(_filename)
651 if not _dir in _sys.path:
652 _sys.path.insert(0, _dir)
653 del _filename, _sys, _dirname, _dir
Walter Dörwald70a6b492004-02-12 17:35:32 +0000654 \n""" % (filename,))
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000655
David Scherer7aced172000-08-15 01:13:23 +0000656 def showsyntaxerror(self, filename=None):
Guido van Rossum33d26892007-08-05 15:29:28 +0000657 """Override Interactive Interpreter method: Use Colorizing
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000658
659 Color the offending position instead of printing it and pointing at it
660 with a caret.
661
662 """
Guido van Rossum33d26892007-08-05 15:29:28 +0000663 tkconsole = self.tkconsole
664 text = tkconsole.text
665 text.tag_remove("ERROR", "1.0", "end")
David Scherer7aced172000-08-15 01:13:23 +0000666 type, value, tb = sys.exc_info()
Ned Deily79746422011-09-14 14:49:14 -0700667 msg = getattr(value, 'msg', '') or value or "<no detail available>"
668 lineno = getattr(value, 'lineno', '') or 1
669 offset = getattr(value, 'offset', '') or 0
Guido van Rossum33d26892007-08-05 15:29:28 +0000670 if offset == 0:
671 lineno += 1 #mark end of offending line
672 if lineno == 1:
673 pos = "iomark + %d chars" % (offset-1)
David Scherer7aced172000-08-15 01:13:23 +0000674 else:
Guido van Rossum33d26892007-08-05 15:29:28 +0000675 pos = "iomark linestart + %d lines + %d chars" % \
676 (lineno-1, offset-1)
677 tkconsole.colorize_syntax_error(text, pos)
678 tkconsole.resetoutput()
679 self.write("SyntaxError: %s\n" % msg)
680 tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000681
682 def showtraceback(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000683 "Extend base class method to reset output properly"
David Scherer7aced172000-08-15 01:13:23 +0000684 self.tkconsole.resetoutput()
685 self.checklinecache()
686 InteractiveInterpreter.showtraceback(self)
Chui Tey5d2af632002-05-26 13:36:41 +0000687 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
688 self.tkconsole.open_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +0000689
690 def checklinecache(self):
691 c = linecache.cache
Guido van Rossum36e0a922007-07-20 04:05:57 +0000692 for key in list(c.keys()):
David Scherer7aced172000-08-15 01:13:23 +0000693 if key[:1] + key[-1:] != "<>":
694 del c[key]
695
Chui Tey5d2af632002-05-26 13:36:41 +0000696 def runcommand(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000697 "Run the code without invoking the debugger"
Chui Tey5d2af632002-05-26 13:36:41 +0000698 # The code better not raise an exception!
699 if self.tkconsole.executing:
Neal Norwitzf4c4f112002-11-30 18:49:10 +0000700 self.display_executing_dialog()
Chui Tey5d2af632002-05-26 13:36:41 +0000701 return 0
702 if self.rpcclt:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000703 self.rpcclt.remotequeue("exec", "runcode", (code,), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000704 else:
Georg Brandl7cae87c2006-09-06 06:51:57 +0000705 exec(code, self.locals)
Chui Tey5d2af632002-05-26 13:36:41 +0000706 return 1
707
David Scherer7aced172000-08-15 01:13:23 +0000708 def runcode(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000709 "Override base class method"
Chui Tey5d2af632002-05-26 13:36:41 +0000710 if self.tkconsole.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000711 self.interp.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000712 self.checklinecache()
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000713 if self.save_warnings_filters is not None:
714 warnings.filters[:] = self.save_warnings_filters
715 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000716 debugger = self.debugger
717 try:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000718 self.tkconsole.beginexecuting()
Thomas Wouterscf297e42007-02-23 15:07:44 +0000719 if not debugger and self.rpcclt is not None:
720 self.active_seq = self.rpcclt.asyncqueue("exec", "runcode",
721 (code,), {})
722 elif debugger:
723 debugger.run(code, self.locals)
724 else:
725 exec(code, self.locals)
726 except SystemExit:
727 if not self.tkconsole.closing:
728 if tkMessageBox.askyesno(
729 "Exit?",
730 "Do you want to exit altogether?",
731 default="yes",
732 master=self.tkconsole.text):
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000733 raise
Thomas Wouterscf297e42007-02-23 15:07:44 +0000734 else:
Guido van Rossum5dc0d972007-02-25 22:37:36 +0000735 self.showtraceback()
Thomas Wouterscf297e42007-02-23 15:07:44 +0000736 else:
737 raise
738 except:
739 if use_subprocess:
740 print("IDLE internal error in runcode()",
741 file=self.tkconsole.stderr)
David Scherer7aced172000-08-15 01:13:23 +0000742 self.showtraceback()
Thomas Wouterscf297e42007-02-23 15:07:44 +0000743 self.tkconsole.endexecuting()
744 else:
745 if self.tkconsole.canceled:
746 self.tkconsole.canceled = False
747 print("KeyboardInterrupt", file=self.tkconsole.stderr)
748 else:
749 self.showtraceback()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000750 finally:
751 if not use_subprocess:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000752 try:
753 self.tkconsole.endexecuting()
754 except AttributeError: # shell may have closed
755 pass
David Scherer7aced172000-08-15 01:13:23 +0000756
757 def write(self, s):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000758 "Override base class method"
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000759 self.tkconsole.stderr.write(s)
David Scherer7aced172000-08-15 01:13:23 +0000760
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000761 def display_port_binding_error(self):
762 tkMessageBox.showerror(
763 "Port Binding Error",
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000764 "IDLE can't bind to a TCP/IP port, which is necessary to "
765 "communicate with its Python execution server. This might be "
766 "because no networking is installed on this computer. "
767 "Run IDLE with the -n command line switch to start without a "
768 "subprocess and refer to Help/IDLE Help 'Running without a "
769 "subprocess' for further details.",
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000770 master=self.tkconsole.text)
771
772 def display_no_subprocess_error(self):
773 tkMessageBox.showerror(
774 "Subprocess Startup Error",
775 "IDLE's subprocess didn't make connection. Either IDLE can't "
776 "start a subprocess or personal firewall software is blocking "
777 "the connection.",
778 master=self.tkconsole.text)
779
780 def display_executing_dialog(self):
781 tkMessageBox.showerror(
782 "Already executing",
783 "The Python Shell window is already executing a command; "
784 "please wait until it is finished.",
785 master=self.tkconsole.text)
786
787
David Scherer7aced172000-08-15 01:13:23 +0000788class PyShell(OutputWindow):
789
790 shell_title = "Python Shell"
791
792 # Override classes
793 ColorDelegator = ModifiedColorDelegator
794 UndoDelegator = ModifiedUndoDelegator
795
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000796 # Override menus
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000797 menu_specs = [
798 ("file", "_File"),
799 ("edit", "_Edit"),
Kurt B. Kaiser4cc5ef52003-01-22 00:23:23 +0000800 ("debug", "_Debug"),
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000801 ("options", "_Options"),
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000802 ("windows", "_Windows"),
803 ("help", "_Help"),
804 ]
David Scherer7aced172000-08-15 01:13:23 +0000805
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000806 if macosxSupport.runningAsOSXApp():
807 del menu_specs[-3]
808 menu_specs[-2] = ("windows", "_Window")
809
810
David Scherer7aced172000-08-15 01:13:23 +0000811 # New classes
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000812 from idlelib.IdleHistory import History
David Scherer7aced172000-08-15 01:13:23 +0000813
814 def __init__(self, flist=None):
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000815 if use_subprocess:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000816 ms = self.menu_specs
817 if ms[2][0] != "shell":
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000818 ms.insert(2, ("shell", "She_ll"))
David Scherer7aced172000-08-15 01:13:23 +0000819 self.interp = ModifiedInterpreter(self)
820 if flist is None:
821 root = Tk()
822 fixwordbreaks(root)
823 root.withdraw()
824 flist = PyShellFileList(root)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000825 #
David Scherer7aced172000-08-15 01:13:23 +0000826 OutputWindow.__init__(self, flist, None, None)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000827 #
Kurt B. Kaiser6af44982005-01-19 00:22:59 +0000828## self.config(usetabs=1, indentwidth=8, context_use_ps1=1)
829 self.usetabs = True
830 # indentwidth must be 8 when using tabs. See note in EditorWindow:
831 self.indentwidth = 8
832 self.context_use_ps1 = True
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000833 #
David Scherer7aced172000-08-15 01:13:23 +0000834 text = self.text
835 text.configure(wrap="char")
836 text.bind("<<newline-and-indent>>", self.enter_callback)
837 text.bind("<<plain-newline-and-indent>>", self.linefeed_callback)
838 text.bind("<<interrupt-execution>>", self.cancel_callback)
David Scherer7aced172000-08-15 01:13:23 +0000839 text.bind("<<end-of-file>>", self.eof_callback)
840 text.bind("<<open-stack-viewer>>", self.open_stack_viewer)
Kurt B. Kaiser57bfe5d2003-05-10 00:09:52 +0000841 text.bind("<<toggle-debugger>>", self.toggle_debugger)
David Scherer7aced172000-08-15 01:13:23 +0000842 text.bind("<<toggle-jit-stack-viewer>>", self.toggle_jit_stack_viewer)
Kurt B. Kaiser8a78cad2007-12-13 03:38:16 +0000843 self.color = color = self.ColorDelegator()
844 self.per.insertfilter(color)
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000845 if use_subprocess:
846 text.bind("<<view-restart>>", self.view_restart_mark)
847 text.bind("<<restart-shell>>", self.restart_shell)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000848 #
David Scherer7aced172000-08-15 01:13:23 +0000849 self.save_stdout = sys.stdout
850 self.save_stderr = sys.stderr
851 self.save_stdin = sys.stdin
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000852 from idlelib import IOBinding
Martin v. Löwisbcc651a2003-06-22 07:52:56 +0000853 self.stdout = PseudoFile(self, "stdout", IOBinding.encoding)
854 self.stderr = PseudoFile(self, "stderr", IOBinding.encoding)
855 self.console = PseudoFile(self, "console", IOBinding.encoding)
Chui Tey5d2af632002-05-26 13:36:41 +0000856 if not use_subprocess:
857 sys.stdout = self.stdout
Kurt B. Kaiser7cec2522007-08-31 04:15:13 +0000858 sys.stderr = self.stderr
Chui Tey5d2af632002-05-26 13:36:41 +0000859 sys.stdin = self
Kurt B. Kaiserf609a342007-12-28 03:57:56 +0000860 try:
861 # page help() text to shell.
862 import pydoc # import must be done here to capture i/o rebinding.
863 # XXX KBK 27Dec07 use a textView someday, but must work w/o subproc
864 pydoc.pager = pydoc.plainpager
865 except:
866 sys.stderr = sys.__stderr__
867 raise
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000868 #
David Scherer7aced172000-08-15 01:13:23 +0000869 self.history = self.History(self.text)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000870 #
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000871 self.pollinterval = 50 # millisec
Chui Tey5d2af632002-05-26 13:36:41 +0000872
Kurt B. Kaiser4d5bc602004-06-06 01:29:22 +0000873 def get_standard_extension_names(self):
874 return idleConf.GetExtensions(shell_only=True)
875
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000876 reading = False
877 executing = False
878 canceled = False
879 endoffile = False
880 closing = False
David Scherer7aced172000-08-15 01:13:23 +0000881
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +0000882 def set_warning_stream(self, stream):
Skip Montanarod9161422004-07-06 21:53:27 +0000883 global warning_stream
884 warning_stream = stream
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +0000885
886 def get_warning_stream(self):
887 return warning_stream
888
David Scherer7aced172000-08-15 01:13:23 +0000889 def toggle_debugger(self, event=None):
890 if self.executing:
891 tkMessageBox.showerror("Don't debug now",
892 "You can only toggle the debugger when idle",
893 master=self.text)
894 self.set_debugger_indicator()
895 return "break"
896 else:
897 db = self.interp.getdebugger()
898 if db:
899 self.close_debugger()
900 else:
901 self.open_debugger()
902
903 def set_debugger_indicator(self):
904 db = self.interp.getdebugger()
905 self.setvar("<<toggle-debugger>>", not not db)
906
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000907 def toggle_jit_stack_viewer(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +0000908 pass # All we need is the variable
909
910 def close_debugger(self):
911 db = self.interp.getdebugger()
912 if db:
913 self.interp.setdebugger(None)
914 db.close()
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000915 if self.interp.rpcclt:
916 RemoteDebugger.close_remote_debugger(self.interp.rpcclt)
David Scherer7aced172000-08-15 01:13:23 +0000917 self.resetoutput()
918 self.console.write("[DEBUG OFF]\n")
919 sys.ps1 = ">>> "
920 self.showprompt()
921 self.set_debugger_indicator()
922
923 def open_debugger(self):
Chui Tey5d2af632002-05-26 13:36:41 +0000924 if self.interp.rpcclt:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000925 dbg_gui = RemoteDebugger.start_remote_debugger(self.interp.rpcclt,
926 self)
927 else:
928 dbg_gui = Debugger.Debugger(self)
929 self.interp.setdebugger(dbg_gui)
930 dbg_gui.load_breakpoints()
Chui Tey5d2af632002-05-26 13:36:41 +0000931 sys.ps1 = "[DEBUG ON]\n>>> "
932 self.showprompt()
933 self.set_debugger_indicator()
934
David Scherer7aced172000-08-15 01:13:23 +0000935 def beginexecuting(self):
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000936 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +0000937 self.resetoutput()
938 self.executing = 1
David Scherer7aced172000-08-15 01:13:23 +0000939
940 def endexecuting(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000941 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +0000942 self.executing = 0
943 self.canceled = 0
Chui Tey5d2af632002-05-26 13:36:41 +0000944 self.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000945
946 def close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000947 "Extend EditorWindow.close()"
David Scherer7aced172000-08-15 01:13:23 +0000948 if self.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000949 response = tkMessageBox.askokcancel(
David Scherer7aced172000-08-15 01:13:23 +0000950 "Kill?",
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000951 "The program is still running!\n Do you want to kill it?",
David Scherer7aced172000-08-15 01:13:23 +0000952 default="ok",
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000953 parent=self.text)
Benjamin Peterson2a691a82008-03-31 01:51:45 +0000954 if response is False:
David Scherer7aced172000-08-15 01:13:23 +0000955 return "cancel"
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +0000956 if self.reading:
957 self.top.quit()
958 self.canceled = True
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000959 self.closing = True
960 # Wait for poll_subprocess() rescheduling to stop
961 self.text.after(2 * self.pollinterval, self.close2)
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000962
963 def close2(self):
964 return EditorWindow.close(self)
David Scherer7aced172000-08-15 01:13:23 +0000965
966 def _close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000967 "Extend EditorWindow._close(), shut down debugger and execution server"
David Scherer7aced172000-08-15 01:13:23 +0000968 self.close_debugger()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000969 if use_subprocess:
970 self.interp.kill_subprocess()
David Scherer7aced172000-08-15 01:13:23 +0000971 # Restore std streams
972 sys.stdout = self.save_stdout
973 sys.stderr = self.save_stderr
974 sys.stdin = self.save_stdin
975 # Break cycles
976 self.interp = None
977 self.console = None
David Scherer7aced172000-08-15 01:13:23 +0000978 self.flist.pyshell = None
979 self.history = None
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000980 EditorWindow._close(self)
David Scherer7aced172000-08-15 01:13:23 +0000981
982 def ispythonsource(self, filename):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000983 "Override EditorWindow method: never remove the colorizer"
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000984 return True
David Scherer7aced172000-08-15 01:13:23 +0000985
986 def short_title(self):
987 return self.shell_title
988
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000989 COPYRIGHT = \
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000990 'Type "copyright", "credits" or "license()" for more information.'
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000991
David Scherer7aced172000-08-15 01:13:23 +0000992 def begin(self):
Kurt B. Kaiser7378df72007-08-11 04:20:51 +0000993 self.text.mark_set("iomark", "insert")
David Scherer7aced172000-08-15 01:13:23 +0000994 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000995 if use_subprocess:
996 nosub = ''
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000997 client = self.interp.start_subprocess()
998 if not client:
999 self.close()
Kurt B. Kaiser76637292004-01-21 22:10:01 +00001000 return False
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001001 else:
1002 nosub = "==== No Subprocess ===="
Raymond Hettingera2a8e8b2009-01-27 00:28:36 +00001003 self.write("Python %s on %s\n%s\n%s" %
1004 (sys.version, sys.platform, self.COPYRIGHT, nosub))
David Scherer7aced172000-08-15 01:13:23 +00001005 self.showprompt()
Georg Brandl14fc4272008-05-17 18:39:55 +00001006 import tkinter
1007 tkinter._default_root = None # 03Jan04 KBK What's this?
Kurt B. Kaiser76637292004-01-21 22:10:01 +00001008 return True
David Scherer7aced172000-08-15 01:13:23 +00001009
1010 def readline(self):
1011 save = self.reading
1012 try:
1013 self.reading = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001014 self.top.mainloop() # nested mainloop()
David Scherer7aced172000-08-15 01:13:23 +00001015 finally:
1016 self.reading = save
1017 line = self.text.get("iomark", "end-1c")
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001018 if len(line) == 0: # may be EOF if we quit our mainloop with Ctrl-C
1019 line = "\n"
David Scherer7aced172000-08-15 01:13:23 +00001020 self.resetoutput()
1021 if self.canceled:
1022 self.canceled = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001023 if not use_subprocess:
1024 raise KeyboardInterrupt
David Scherer7aced172000-08-15 01:13:23 +00001025 if self.endoffile:
1026 self.endoffile = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001027 line = ""
David Scherer7aced172000-08-15 01:13:23 +00001028 return line
1029
1030 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001031 return True
David Scherer7aced172000-08-15 01:13:23 +00001032
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001033 def cancel_callback(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +00001034 try:
1035 if self.text.compare("sel.first", "!=", "sel.last"):
1036 return # Active selection -- always use default binding
1037 except:
1038 pass
1039 if not (self.executing or self.reading):
1040 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001041 self.interp.write("KeyboardInterrupt\n")
David Scherer7aced172000-08-15 01:13:23 +00001042 self.showprompt()
1043 return "break"
1044 self.endoffile = 0
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001045 self.canceled = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001046 if (self.executing and self.interp.rpcclt):
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +00001047 if self.interp.getdebugger():
1048 self.interp.restart_subprocess()
1049 else:
1050 self.interp.interrupt_subprocess()
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001051 if self.reading:
1052 self.top.quit() # exit the nested mainloop() in readline()
David Scherer7aced172000-08-15 01:13:23 +00001053 return "break"
1054
1055 def eof_callback(self, event):
1056 if self.executing and not self.reading:
1057 return # Let the default binding (delete next char) take over
1058 if not (self.text.compare("iomark", "==", "insert") and
1059 self.text.compare("insert", "==", "end-1c")):
1060 return # Let the default binding (delete next char) take over
1061 if not self.executing:
David Scherer7aced172000-08-15 01:13:23 +00001062 self.resetoutput()
1063 self.close()
1064 else:
1065 self.canceled = 0
1066 self.endoffile = 1
1067 self.top.quit()
1068 return "break"
1069
David Scherer7aced172000-08-15 01:13:23 +00001070 def linefeed_callback(self, event):
1071 # Insert a linefeed without entering anything (still autoindented)
1072 if self.reading:
1073 self.text.insert("insert", "\n")
1074 self.text.see("insert")
1075 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001076 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001077 return "break"
1078
1079 def enter_callback(self, event):
1080 if self.executing and not self.reading:
1081 return # Let the default binding (insert '\n') take over
1082 # If some text is selected, recall the selection
1083 # (but only if this before the I/O mark)
1084 try:
1085 sel = self.text.get("sel.first", "sel.last")
1086 if sel:
1087 if self.text.compare("sel.last", "<=", "iomark"):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001088 self.recall(sel, event)
David Scherer7aced172000-08-15 01:13:23 +00001089 return "break"
1090 except:
1091 pass
1092 # If we're strictly before the line containing iomark, recall
1093 # the current line, less a leading prompt, less leading or
1094 # trailing whitespace
1095 if self.text.compare("insert", "<", "iomark linestart"):
1096 # Check if there's a relevant stdin range -- if so, use it
1097 prev = self.text.tag_prevrange("stdin", "insert")
1098 if prev and self.text.compare("insert", "<", prev[1]):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001099 self.recall(self.text.get(prev[0], prev[1]), event)
David Scherer7aced172000-08-15 01:13:23 +00001100 return "break"
1101 next = self.text.tag_nextrange("stdin", "insert")
1102 if next and self.text.compare("insert lineend", ">=", next[0]):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001103 self.recall(self.text.get(next[0], next[1]), event)
David Scherer7aced172000-08-15 01:13:23 +00001104 return "break"
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001105 # No stdin mark -- just get the current line, less any prompt
Kurt B. Kaiserb1754452005-11-18 22:05:48 +00001106 indices = self.text.tag_nextrange("console", "insert linestart")
1107 if indices and \
1108 self.text.compare(indices[0], "<=", "insert linestart"):
1109 self.recall(self.text.get(indices[1], "insert lineend"), event)
1110 else:
1111 self.recall(self.text.get("insert linestart", "insert lineend"), event)
David Scherer7aced172000-08-15 01:13:23 +00001112 return "break"
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001113 # If we're between the beginning of the line and the iomark, i.e.
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001114 # in the prompt area, move to the end of the prompt
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001115 if self.text.compare("insert", "<", "iomark"):
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001116 self.text.mark_set("insert", "iomark")
David Scherer7aced172000-08-15 01:13:23 +00001117 # If we're in the current input and there's only whitespace
1118 # beyond the cursor, erase that whitespace first
1119 s = self.text.get("insert", "end-1c")
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001120 if s and not s.strip():
David Scherer7aced172000-08-15 01:13:23 +00001121 self.text.delete("insert", "end-1c")
1122 # If we're in the current input before its last line,
1123 # insert a newline right at the insert point
1124 if self.text.compare("insert", "<", "end-1c linestart"):
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001125 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001126 return "break"
1127 # We're in the last line; append a newline and submit it
1128 self.text.mark_set("insert", "end-1c")
1129 if self.reading:
1130 self.text.insert("insert", "\n")
1131 self.text.see("insert")
1132 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001133 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001134 self.text.tag_add("stdin", "iomark", "end-1c")
1135 self.text.update_idletasks()
1136 if self.reading:
Neal Norwitzce96f692006-03-17 06:49:51 +00001137 self.top.quit() # Break out of recursive mainloop()
David Scherer7aced172000-08-15 01:13:23 +00001138 else:
1139 self.runit()
1140 return "break"
1141
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001142 def recall(self, s, event):
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001143 # remove leading and trailing empty or whitespace lines
1144 s = re.sub(r'^\s*\n', '' , s)
1145 s = re.sub(r'\n\s*$', '', s)
1146 lines = s.split('\n')
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001147 self.text.undo_block_start()
1148 try:
1149 self.text.tag_remove("sel", "1.0", "end")
1150 self.text.mark_set("insert", "end-1c")
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001151 prefix = self.text.get("insert linestart", "insert")
1152 if prefix.rstrip().endswith(':'):
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001153 self.newline_and_indent_event(event)
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001154 prefix = self.text.get("insert linestart", "insert")
1155 self.text.insert("insert", lines[0].strip())
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001156 if len(lines) > 1:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001157 orig_base_indent = re.search(r'^([ \t]*)', lines[0]).group(0)
1158 new_base_indent = re.search(r'^([ \t]*)', prefix).group(0)
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001159 for line in lines[1:]:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001160 if line.startswith(orig_base_indent):
1161 # replace orig base indentation with new indentation
1162 line = new_base_indent + line[len(orig_base_indent):]
1163 self.text.insert('insert', '\n'+line.rstrip())
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001164 finally:
1165 self.text.see("insert")
1166 self.text.undo_block_stop()
David Scherer7aced172000-08-15 01:13:23 +00001167
1168 def runit(self):
1169 line = self.text.get("iomark", "end-1c")
1170 # Strip off last newline and surrounding whitespace.
1171 # (To allow you to hit return twice to end a statement.)
1172 i = len(line)
1173 while i > 0 and line[i-1] in " \t":
1174 i = i-1
1175 if i > 0 and line[i-1] == "\n":
1176 i = i-1
1177 while i > 0 and line[i-1] in " \t":
1178 i = i-1
1179 line = line[:i]
1180 more = self.interp.runsource(line)
David Scherer7aced172000-08-15 01:13:23 +00001181
David Scherer7aced172000-08-15 01:13:23 +00001182 def open_stack_viewer(self, event=None):
Chui Tey5d2af632002-05-26 13:36:41 +00001183 if self.interp.rpcclt:
1184 return self.interp.remote_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +00001185 try:
1186 sys.last_traceback
1187 except:
1188 tkMessageBox.showerror("No stack trace",
1189 "There is no stack trace yet.\n"
1190 "(sys.last_traceback is not defined)",
1191 master=self.text)
1192 return
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +00001193 from idlelib.StackViewer import StackBrowser
David Scherer7aced172000-08-15 01:13:23 +00001194 sv = StackBrowser(self.root, self.flist)
1195
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001196 def view_restart_mark(self, event=None):
1197 self.text.see("iomark")
1198 self.text.see("restart")
1199
1200 def restart_shell(self, event=None):
Terry Jan Reedyda4c4672012-01-31 02:26:32 -05001201 "Callback for Run/Restart Shell Cntl-F6"
1202 self.interp.restart_subprocess(with_cwd=True)
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001203
David Scherer7aced172000-08-15 01:13:23 +00001204 def showprompt(self):
1205 self.resetoutput()
1206 try:
1207 s = str(sys.ps1)
1208 except:
1209 s = ""
1210 self.console.write(s)
1211 self.text.mark_set("insert", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001212 self.set_line_and_column()
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +00001213 self.io.reset_undo()
David Scherer7aced172000-08-15 01:13:23 +00001214
1215 def resetoutput(self):
1216 source = self.text.get("iomark", "end-1c")
1217 if self.history:
1218 self.history.history_store(source)
1219 if self.text.get("end-2c") != "\n":
1220 self.text.insert("end-1c", "\n")
1221 self.text.mark_set("iomark", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001222 self.set_line_and_column()
David Scherer7aced172000-08-15 01:13:23 +00001223
1224 def write(self, s, tags=()):
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001225 try:
1226 self.text.mark_gravity("iomark", "right")
1227 OutputWindow.write(self, s, tags, "iomark")
1228 self.text.mark_gravity("iomark", "left")
1229 except:
Kurt B. Kaisercbbe98f2007-08-12 01:52:35 +00001230 raise ###pass # ### 11Aug07 KBK if we are expecting exceptions
1231 # let's find out what they are and be specific.
David Scherer7aced172000-08-15 01:13:23 +00001232 if self.canceled:
1233 self.canceled = 0
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001234 if not use_subprocess:
1235 raise KeyboardInterrupt
David Scherer7aced172000-08-15 01:13:23 +00001236
Kurt B. Kaiserdcba6622004-12-21 22:10:32 +00001237class PseudoFile(object):
David Scherer7aced172000-08-15 01:13:23 +00001238
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001239 def __init__(self, shell, tags, encoding=None):
David Scherer7aced172000-08-15 01:13:23 +00001240 self.shell = shell
1241 self.tags = tags
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001242 self.encoding = encoding
David Scherer7aced172000-08-15 01:13:23 +00001243
1244 def write(self, s):
1245 self.shell.write(s, self.tags)
1246
Kurt B. Kaiser66aaf742007-08-09 18:00:23 +00001247 def writelines(self, lines):
1248 for line in lines:
1249 self.write(line)
David Scherer7aced172000-08-15 01:13:23 +00001250
1251 def flush(self):
1252 pass
1253
1254 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001255 return True
David Scherer7aced172000-08-15 01:13:23 +00001256
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001257
David Scherer7aced172000-08-15 01:13:23 +00001258usage_msg = """\
David Scherer7aced172000-08-15 01:13:23 +00001259
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001260USAGE: idle [-deins] [-t title] [file]*
1261 idle [-dns] [-t title] (-c cmd | -r file) [arg]*
1262 idle [-dns] [-t title] - [arg]*
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001263
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001264 -h print this help message and exit
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001265 -n run IDLE without a subprocess (see Help/IDLE Help for details)
David Scherer7aced172000-08-15 01:13:23 +00001266
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001267The following options will override the IDLE 'settings' configuration:
Kurt B. Kaiser96d88422001-07-17 04:59:01 +00001268
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001269 -e open an edit window
1270 -i open a shell window
1271
1272The following options imply -i and will open a shell:
1273
1274 -c cmd run the command in a shell, or
1275 -r file run script from file
1276
1277 -d enable the debugger
1278 -s run $IDLESTARTUP or $PYTHONSTARTUP before anything else
1279 -t title set title of shell window
1280
1281A default edit window will be bypassed when -c, -r, or - are used.
1282
1283[arg]* are passed to the command (-c) or script (-r) in sys.argv[1:].
1284
1285Examples:
1286
1287idle
1288 Open an edit window or shell depending on IDLE's configuration.
1289
1290idle foo.py foobar.py
1291 Edit the files, also open a shell if configured to start with shell.
1292
1293idle -est "Baz" foo.py
1294 Run $IDLESTARTUP or $PYTHONSTARTUP, edit foo.py, and open a shell
1295 window with the title "Baz".
1296
Neal Norwitz752abd02008-05-13 04:55:24 +00001297idle -c "import sys; print(sys.argv)" "foo"
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001298 Open a shell window and run the command, passing "-c" in sys.argv[0]
1299 and "foo" in sys.argv[1].
1300
1301idle -d -s -r foo.py "Hello World"
1302 Open a shell window, run a startup script, enable the debugger, and
1303 run foo.py, passing "foo.py" in sys.argv[0] and "Hello World" in
1304 sys.argv[1].
1305
Neal Norwitz752abd02008-05-13 04:55:24 +00001306echo "import sys; print(sys.argv)" | idle - "foobar"
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001307 Open a shell window, run the script piped in, passing '' in sys.argv[0]
1308 and "foobar" in sys.argv[1].
David Scherer7aced172000-08-15 01:13:23 +00001309"""
1310
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001311def main():
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001312 global flist, root, use_subprocess
David Scherer7aced172000-08-15 01:13:23 +00001313
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001314 use_subprocess = True
Kurt B. Kaisere866c812009-04-04 21:07:39 +00001315 enable_shell = True
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001316 enable_edit = False
1317 debug = False
1318 cmd = None
1319 script = None
1320 startup = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001321 try:
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001322 opts, args = getopt.getopt(sys.argv[1:], "c:deihnr:st:")
Guido van Rossumb940e112007-01-10 16:19:56 +00001323 except getopt.error as msg:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001324 sys.stderr.write("Error: %s\n" % str(msg))
1325 sys.stderr.write(usage_msg)
1326 sys.exit(2)
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001327 for o, a in opts:
1328 if o == '-c':
1329 cmd = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001330 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001331 if o == '-d':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001332 debug = True
1333 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001334 if o == '-e':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001335 enable_edit = True
Kurt B. Kaisere866c812009-04-04 21:07:39 +00001336 enable_shell = False
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001337 if o == '-h':
1338 sys.stdout.write(usage_msg)
1339 sys.exit()
1340 if o == '-i':
1341 enable_shell = True
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001342 if o == '-n':
1343 use_subprocess = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001344 if o == '-r':
1345 script = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001346 if os.path.isfile(script):
1347 pass
1348 else:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001349 print("No script file: ", script)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001350 sys.exit()
1351 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001352 if o == '-s':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001353 startup = True
1354 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001355 if o == '-t':
1356 PyShell.shell_title = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001357 enable_shell = True
1358 if args and args[0] == '-':
1359 cmd = sys.stdin.read()
1360 enable_shell = True
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001361 # process sys.argv and sys.path:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001362 for i in range(len(sys.path)):
1363 sys.path[i] = os.path.abspath(sys.path[i])
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001364 if args and args[0] == '-':
1365 sys.argv = [''] + args[1:]
1366 elif cmd:
1367 sys.argv = ['-c'] + args
1368 elif script:
1369 sys.argv = [script] + args
1370 elif args:
1371 enable_edit = True
1372 pathx = []
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001373 for filename in args:
1374 pathx.append(os.path.dirname(filename))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001375 for dir in pathx:
1376 dir = os.path.abspath(dir)
1377 if not dir in sys.path:
1378 sys.path.insert(0, dir)
Kurt B. Kaiserff002b92002-12-21 21:39:11 +00001379 else:
Neal Norwitzd082b6e2007-08-26 23:37:53 +00001380 dir = os.getcwd()
1381 if dir not in sys.path:
Kurt B. Kaiserff002b92002-12-21 21:39:11 +00001382 sys.path.insert(0, dir)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001383 # check the IDLE settings configuration (but command line overrides)
1384 edit_start = idleConf.GetOption('main', 'General',
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001385 'editor-on-startup', type='bool')
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001386 enable_edit = enable_edit or edit_start
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001387 # start editor and/or shell windows:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001388 root = Tk(className="Idle")
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001389
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001390 fixwordbreaks(root)
1391 root.withdraw()
1392 flist = PyShellFileList(root)
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001393 macosxSupport.setupApp(root, flist)
1394
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001395 if enable_edit:
1396 if not (cmd or script):
Andrew Svetlov0f71f442012-03-21 13:23:41 +02001397 for filename in args[:]:
1398 if flist.open(filename) is None:
1399 # filename is a directory actually, disconsider it
1400 args.remove(filename)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001401 if not args:
1402 flist.new()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001403 if enable_shell:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001404 shell = flist.open_shell()
1405 if not shell:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001406 return # couldn't open shell
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001407
1408 if macosxSupport.runningAsOSXApp() and flist.dict:
1409 # On OSX: when the user has double-clicked on a file that causes
1410 # IDLE to be launched the shell window will open just in front of
1411 # the file she wants to see. Lower the interpreter window when
1412 # there are open files.
1413 shell.top.lower()
1414
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001415 shell = flist.pyshell
1416 # handle remaining options:
1417 if debug:
1418 shell.open_debugger()
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001419 if startup:
1420 filename = os.environ.get("IDLESTARTUP") or \
1421 os.environ.get("PYTHONSTARTUP")
1422 if filename and os.path.isfile(filename):
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001423 shell.interp.execfile(filename)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001424 if shell and cmd or script:
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001425 shell.interp.runcommand("""if 1:
1426 import sys as _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001427 _sys.argv = %r
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001428 del _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001429 \n""" % (sys.argv,))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001430 if cmd:
1431 shell.interp.execsource(cmd)
1432 elif script:
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001433 shell.interp.prepend_syspath(script)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001434 shell.interp.execfile(script)
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001435
Ned Deily4ce92b22011-01-15 04:37:12 +00001436 # Check for problematic OS X Tk versions and print a warning message
1437 # in the IDLE shell window; this is less intrusive than always opening
1438 # a separate window.
1439 tkversionwarning = macosxSupport.tkVersionWarning(root)
1440 if tkversionwarning:
1441 shell.interp.runcommand(''.join(("print('", tkversionwarning, "')")))
1442
Terry Jan Reedycd6b8c62012-05-26 20:23:45 -04001443 while flist.inversedict: # keep IDLE running while files are open.
1444 root.mainloop()
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001445 root.destroy()
1446
David Scherer7aced172000-08-15 01:13:23 +00001447if __name__ == "__main__":
Kurt B. Kaiser9e8b8282003-06-15 17:38:45 +00001448 sys.modules['PyShell'] = sys.modules['__main__']
David Scherer7aced172000-08-15 01:13:23 +00001449 main()