blob: 9df8957310ca0d6e1051c2d6a8230c378c629d7b [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:
Ned Deily55f87572011-11-05 22:36:44 -0700476 self.rpcclt.listening_sock.close()
477 except AttributeError: # no socket
478 pass
479 try:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000480 self.rpcclt.close()
481 except AttributeError: # no socket
482 pass
Ned Deilye5cad232011-08-02 18:47:13 -0700483 self.terminate_subprocess()
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000484 self.tkconsole.executing = False
485 self.rpcclt = None
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000486
Ned Deilye5cad232011-08-02 18:47:13 -0700487 def terminate_subprocess(self):
488 "Make sure subprocess is terminated"
489 try:
490 self.rpcsubproc.kill()
491 except OSError:
492 # process already terminated
493 return
494 else:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000495 try:
Ned Deilye5cad232011-08-02 18:47:13 -0700496 self.rpcsubproc.wait()
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000497 except OSError:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000498 return
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000499
Terry Jan Reedyda4c4672012-01-31 02:26:32 -0500500 def transfer_path(self, with_cwd=False):
501 if with_cwd: # Issue 13506
502 path = [''] # include Current Working Directory
503 path.extend(sys.path)
504 else:
505 path = sys.path
Terry Jan Reedy4d82ade2012-01-31 02:57:29 -0500506
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000507 self.runcommand("""if 1:
508 import sys as _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +0000509 _sys.path = %r
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000510 del _sys
Terry Jan Reedyda4c4672012-01-31 02:26:32 -0500511 \n""" % (path,))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000512
Chui Tey5d2af632002-05-26 13:36:41 +0000513 active_seq = None
514
515 def poll_subprocess(self):
516 clt = self.rpcclt
517 if clt is None:
518 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000519 try:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000520 response = clt.pollresponse(self.active_seq, wait=0.05)
521 except (EOFError, IOError, KeyboardInterrupt):
522 # lost connection or subprocess terminated itself, restart
523 # [the KBI is from rpc.SocketIO.handle_EOF()]
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000524 if self.tkconsole.closing:
525 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000526 response = None
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000527 self.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000528 if response:
529 self.tkconsole.resetoutput()
530 self.active_seq = None
531 how, what = response
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000532 console = self.tkconsole.console
Chui Tey5d2af632002-05-26 13:36:41 +0000533 if how == "OK":
534 if what is not None:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000535 print(repr(what), file=console)
Chui Tey5d2af632002-05-26 13:36:41 +0000536 elif how == "EXCEPTION":
Chui Tey5d2af632002-05-26 13:36:41 +0000537 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
538 self.remote_stack_viewer()
539 elif how == "ERROR":
Kurt B. Kaiser0930c432002-12-06 21:45:24 +0000540 errmsg = "PyShell.ModifiedInterpreter: Subprocess ERROR:\n"
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000541 print(errmsg, what, file=sys.__stderr__)
542 print(errmsg, what, file=console)
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000543 # we received a response to the currently active seq number:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000544 try:
545 self.tkconsole.endexecuting()
546 except AttributeError: # shell may have closed
547 pass
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000548 # Reschedule myself
549 if not self.tkconsole.closing:
550 self.tkconsole.text.after(self.tkconsole.pollinterval,
551 self.poll_subprocess)
Chui Tey5d2af632002-05-26 13:36:41 +0000552
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000553 debugger = None
554
555 def setdebugger(self, debugger):
556 self.debugger = debugger
557
558 def getdebugger(self):
559 return self.debugger
560
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000561 def open_remote_stack_viewer(self):
562 """Initiate the remote stack viewer from a separate thread.
563
564 This method is called from the subprocess, and by returning from this
565 method we allow the subprocess to unblock. After a bit the shell
566 requests the subprocess to open the remote stack viewer which returns a
Ezio Melotti60861182010-07-23 16:48:22 +0000567 static object looking at the last exception. It is queried through
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000568 the RPC mechanism.
569
570 """
571 self.tkconsole.text.after(300, self.remote_stack_viewer)
572 return
573
Chui Tey5d2af632002-05-26 13:36:41 +0000574 def remote_stack_viewer(self):
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000575 from idlelib import RemoteObjectBrowser
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000576 oid = self.rpcclt.remotequeue("exec", "stackviewer", ("flist",), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000577 if oid is None:
578 self.tkconsole.root.bell()
579 return
580 item = RemoteObjectBrowser.StubObjectTreeItem(self.rpcclt, oid)
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000581 from idlelib.TreeWidget import ScrolledCanvas, TreeNode
Chui Tey5d2af632002-05-26 13:36:41 +0000582 top = Toplevel(self.tkconsole.root)
Kurt B. Kaiser73360a32004-03-08 18:15:31 +0000583 theme = idleConf.GetOption('main','Theme','name')
584 background = idleConf.GetHighlight(theme, 'normal')['background']
585 sc = ScrolledCanvas(top, bg=background, highlightthickness=0)
Chui Tey5d2af632002-05-26 13:36:41 +0000586 sc.frame.pack(expand=1, fill="both")
587 node = TreeNode(sc.canvas, None, item)
588 node.expand()
589 # XXX Should GC the remote tree when closing the window
590
David Scherer7aced172000-08-15 01:13:23 +0000591 gid = 0
592
593 def execsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000594 "Like runsource() but assumes complete exec source"
David Scherer7aced172000-08-15 01:13:23 +0000595 filename = self.stuffsource(source)
596 self.execfile(filename, source)
597
598 def execfile(self, filename, source=None):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000599 "Execute an existing file"
David Scherer7aced172000-08-15 01:13:23 +0000600 if source is None:
Victor Stinner979482a2011-09-02 01:00:40 +0200601 with tokenize.open(filename) as fp:
Victor Stinner85c67722011-09-02 00:57:04 +0200602 source = fp.read()
David Scherer7aced172000-08-15 01:13:23 +0000603 try:
604 code = compile(source, filename, "exec")
605 except (OverflowError, SyntaxError):
606 self.tkconsole.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000607 tkerr = self.tkconsole.stderr
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000608 print('*** Error in script or command!\n', file=tkerr)
609 print('Traceback (most recent call last):', file=tkerr)
David Scherer7aced172000-08-15 01:13:23 +0000610 InteractiveInterpreter.showsyntaxerror(self, filename)
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000611 self.tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000612 else:
613 self.runcode(code)
614
615 def runsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000616 "Extend base class method: Stuff the source in the line cache first"
David Scherer7aced172000-08-15 01:13:23 +0000617 filename = self.stuffsource(source)
618 self.more = 0
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000619 self.save_warnings_filters = warnings.filters[:]
620 warnings.filterwarnings(action="error", category=SyntaxWarning)
Martin v. Löwis98ff8982007-08-13 06:03:15 +0000621 # at the moment, InteractiveInterpreter expects str
622 assert isinstance(source, str)
623 #if isinstance(source, str):
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000624 # from idlelib import IOBinding
Martin v. Löwis98ff8982007-08-13 06:03:15 +0000625 # try:
626 # source = source.encode(IOBinding.encoding)
627 # except UnicodeError:
628 # self.tkconsole.resetoutput()
629 # self.write("Unsupported characters in input\n")
630 # return
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000631 try:
Kurt B. Kaiser935ea9a2005-05-10 03:44:24 +0000632 # InteractiveInterpreter.runsource() calls its runcode() method,
633 # which is overridden (see below)
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000634 return InteractiveInterpreter.runsource(self, source, filename)
635 finally:
636 if self.save_warnings_filters is not None:
637 warnings.filters[:] = self.save_warnings_filters
638 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000639
640 def stuffsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000641 "Stuff source in the filename cache"
David Scherer7aced172000-08-15 01:13:23 +0000642 filename = "<pyshell#%d>" % self.gid
643 self.gid = self.gid + 1
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000644 lines = source.split("\n")
David Scherer7aced172000-08-15 01:13:23 +0000645 linecache.cache[filename] = len(source)+1, 0, lines, filename
646 return filename
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000647
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000648 def prepend_syspath(self, filename):
649 "Prepend sys.path with file's directory if not already included"
650 self.runcommand("""if 1:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000651 _filename = %r
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000652 import sys as _sys
653 from os.path import dirname as _dirname
654 _dir = _dirname(_filename)
655 if not _dir in _sys.path:
656 _sys.path.insert(0, _dir)
657 del _filename, _sys, _dirname, _dir
Walter Dörwald70a6b492004-02-12 17:35:32 +0000658 \n""" % (filename,))
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000659
David Scherer7aced172000-08-15 01:13:23 +0000660 def showsyntaxerror(self, filename=None):
Guido van Rossum33d26892007-08-05 15:29:28 +0000661 """Override Interactive Interpreter method: Use Colorizing
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000662
663 Color the offending position instead of printing it and pointing at it
664 with a caret.
665
666 """
Guido van Rossum33d26892007-08-05 15:29:28 +0000667 tkconsole = self.tkconsole
668 text = tkconsole.text
669 text.tag_remove("ERROR", "1.0", "end")
David Scherer7aced172000-08-15 01:13:23 +0000670 type, value, tb = sys.exc_info()
Ned Deily79746422011-09-14 14:49:14 -0700671 msg = getattr(value, 'msg', '') or value or "<no detail available>"
672 lineno = getattr(value, 'lineno', '') or 1
673 offset = getattr(value, 'offset', '') or 0
Guido van Rossum33d26892007-08-05 15:29:28 +0000674 if offset == 0:
675 lineno += 1 #mark end of offending line
676 if lineno == 1:
677 pos = "iomark + %d chars" % (offset-1)
David Scherer7aced172000-08-15 01:13:23 +0000678 else:
Guido van Rossum33d26892007-08-05 15:29:28 +0000679 pos = "iomark linestart + %d lines + %d chars" % \
680 (lineno-1, offset-1)
681 tkconsole.colorize_syntax_error(text, pos)
682 tkconsole.resetoutput()
683 self.write("SyntaxError: %s\n" % msg)
684 tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000685
686 def showtraceback(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000687 "Extend base class method to reset output properly"
David Scherer7aced172000-08-15 01:13:23 +0000688 self.tkconsole.resetoutput()
689 self.checklinecache()
690 InteractiveInterpreter.showtraceback(self)
Chui Tey5d2af632002-05-26 13:36:41 +0000691 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
692 self.tkconsole.open_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +0000693
694 def checklinecache(self):
695 c = linecache.cache
Guido van Rossum36e0a922007-07-20 04:05:57 +0000696 for key in list(c.keys()):
David Scherer7aced172000-08-15 01:13:23 +0000697 if key[:1] + key[-1:] != "<>":
698 del c[key]
699
Chui Tey5d2af632002-05-26 13:36:41 +0000700 def runcommand(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000701 "Run the code without invoking the debugger"
Chui Tey5d2af632002-05-26 13:36:41 +0000702 # The code better not raise an exception!
703 if self.tkconsole.executing:
Neal Norwitzf4c4f112002-11-30 18:49:10 +0000704 self.display_executing_dialog()
Chui Tey5d2af632002-05-26 13:36:41 +0000705 return 0
706 if self.rpcclt:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000707 self.rpcclt.remotequeue("exec", "runcode", (code,), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000708 else:
Georg Brandl7cae87c2006-09-06 06:51:57 +0000709 exec(code, self.locals)
Chui Tey5d2af632002-05-26 13:36:41 +0000710 return 1
711
David Scherer7aced172000-08-15 01:13:23 +0000712 def runcode(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000713 "Override base class method"
Chui Tey5d2af632002-05-26 13:36:41 +0000714 if self.tkconsole.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000715 self.interp.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000716 self.checklinecache()
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000717 if self.save_warnings_filters is not None:
718 warnings.filters[:] = self.save_warnings_filters
719 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000720 debugger = self.debugger
721 try:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000722 self.tkconsole.beginexecuting()
Thomas Wouterscf297e42007-02-23 15:07:44 +0000723 if not debugger and self.rpcclt is not None:
724 self.active_seq = self.rpcclt.asyncqueue("exec", "runcode",
725 (code,), {})
726 elif debugger:
727 debugger.run(code, self.locals)
728 else:
729 exec(code, self.locals)
730 except SystemExit:
731 if not self.tkconsole.closing:
732 if tkMessageBox.askyesno(
733 "Exit?",
734 "Do you want to exit altogether?",
735 default="yes",
736 master=self.tkconsole.text):
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000737 raise
Thomas Wouterscf297e42007-02-23 15:07:44 +0000738 else:
Guido van Rossum5dc0d972007-02-25 22:37:36 +0000739 self.showtraceback()
Thomas Wouterscf297e42007-02-23 15:07:44 +0000740 else:
741 raise
742 except:
743 if use_subprocess:
744 print("IDLE internal error in runcode()",
745 file=self.tkconsole.stderr)
David Scherer7aced172000-08-15 01:13:23 +0000746 self.showtraceback()
Thomas Wouterscf297e42007-02-23 15:07:44 +0000747 self.tkconsole.endexecuting()
748 else:
749 if self.tkconsole.canceled:
750 self.tkconsole.canceled = False
751 print("KeyboardInterrupt", file=self.tkconsole.stderr)
752 else:
753 self.showtraceback()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000754 finally:
755 if not use_subprocess:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000756 try:
757 self.tkconsole.endexecuting()
758 except AttributeError: # shell may have closed
759 pass
David Scherer7aced172000-08-15 01:13:23 +0000760
761 def write(self, s):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000762 "Override base class method"
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000763 self.tkconsole.stderr.write(s)
David Scherer7aced172000-08-15 01:13:23 +0000764
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000765 def display_port_binding_error(self):
766 tkMessageBox.showerror(
767 "Port Binding Error",
Kurt B. Kaisere866c812009-04-04 21:07:39 +0000768 "IDLE can't bind to a TCP/IP port, which is necessary to "
769 "communicate with its Python execution server. This might be "
770 "because no networking is installed on this computer. "
771 "Run IDLE with the -n command line switch to start without a "
772 "subprocess and refer to Help/IDLE Help 'Running without a "
773 "subprocess' for further details.",
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000774 master=self.tkconsole.text)
775
776 def display_no_subprocess_error(self):
777 tkMessageBox.showerror(
778 "Subprocess Startup Error",
779 "IDLE's subprocess didn't make connection. Either IDLE can't "
780 "start a subprocess or personal firewall software is blocking "
781 "the connection.",
782 master=self.tkconsole.text)
783
784 def display_executing_dialog(self):
785 tkMessageBox.showerror(
786 "Already executing",
787 "The Python Shell window is already executing a command; "
788 "please wait until it is finished.",
789 master=self.tkconsole.text)
790
791
David Scherer7aced172000-08-15 01:13:23 +0000792class PyShell(OutputWindow):
793
794 shell_title = "Python Shell"
795
796 # Override classes
797 ColorDelegator = ModifiedColorDelegator
798 UndoDelegator = ModifiedUndoDelegator
799
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000800 # Override menus
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000801 menu_specs = [
802 ("file", "_File"),
803 ("edit", "_Edit"),
Kurt B. Kaiser4cc5ef52003-01-22 00:23:23 +0000804 ("debug", "_Debug"),
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000805 ("options", "_Options"),
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000806 ("windows", "_Windows"),
807 ("help", "_Help"),
808 ]
David Scherer7aced172000-08-15 01:13:23 +0000809
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000810 if macosxSupport.runningAsOSXApp():
811 del menu_specs[-3]
812 menu_specs[-2] = ("windows", "_Window")
813
814
David Scherer7aced172000-08-15 01:13:23 +0000815 # New classes
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000816 from idlelib.IdleHistory import History
David Scherer7aced172000-08-15 01:13:23 +0000817
818 def __init__(self, flist=None):
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000819 if use_subprocess:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000820 ms = self.menu_specs
821 if ms[2][0] != "shell":
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000822 ms.insert(2, ("shell", "She_ll"))
David Scherer7aced172000-08-15 01:13:23 +0000823 self.interp = ModifiedInterpreter(self)
824 if flist is None:
825 root = Tk()
826 fixwordbreaks(root)
827 root.withdraw()
828 flist = PyShellFileList(root)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000829 #
David Scherer7aced172000-08-15 01:13:23 +0000830 OutputWindow.__init__(self, flist, None, None)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000831 #
Kurt B. Kaiser6af44982005-01-19 00:22:59 +0000832## self.config(usetabs=1, indentwidth=8, context_use_ps1=1)
833 self.usetabs = True
834 # indentwidth must be 8 when using tabs. See note in EditorWindow:
835 self.indentwidth = 8
836 self.context_use_ps1 = True
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000837 #
David Scherer7aced172000-08-15 01:13:23 +0000838 text = self.text
839 text.configure(wrap="char")
840 text.bind("<<newline-and-indent>>", self.enter_callback)
841 text.bind("<<plain-newline-and-indent>>", self.linefeed_callback)
842 text.bind("<<interrupt-execution>>", self.cancel_callback)
David Scherer7aced172000-08-15 01:13:23 +0000843 text.bind("<<end-of-file>>", self.eof_callback)
844 text.bind("<<open-stack-viewer>>", self.open_stack_viewer)
Kurt B. Kaiser57bfe5d2003-05-10 00:09:52 +0000845 text.bind("<<toggle-debugger>>", self.toggle_debugger)
David Scherer7aced172000-08-15 01:13:23 +0000846 text.bind("<<toggle-jit-stack-viewer>>", self.toggle_jit_stack_viewer)
Kurt B. Kaiser8a78cad2007-12-13 03:38:16 +0000847 self.color = color = self.ColorDelegator()
848 self.per.insertfilter(color)
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000849 if use_subprocess:
850 text.bind("<<view-restart>>", self.view_restart_mark)
851 text.bind("<<restart-shell>>", self.restart_shell)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000852 #
David Scherer7aced172000-08-15 01:13:23 +0000853 self.save_stdout = sys.stdout
854 self.save_stderr = sys.stderr
855 self.save_stdin = sys.stdin
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +0000856 from idlelib import IOBinding
Martin v. Löwisbcc651a2003-06-22 07:52:56 +0000857 self.stdout = PseudoFile(self, "stdout", IOBinding.encoding)
858 self.stderr = PseudoFile(self, "stderr", IOBinding.encoding)
859 self.console = PseudoFile(self, "console", IOBinding.encoding)
Chui Tey5d2af632002-05-26 13:36:41 +0000860 if not use_subprocess:
861 sys.stdout = self.stdout
Kurt B. Kaiser7cec2522007-08-31 04:15:13 +0000862 sys.stderr = self.stderr
Chui Tey5d2af632002-05-26 13:36:41 +0000863 sys.stdin = self
Kurt B. Kaiserf609a342007-12-28 03:57:56 +0000864 try:
865 # page help() text to shell.
866 import pydoc # import must be done here to capture i/o rebinding.
867 # XXX KBK 27Dec07 use a textView someday, but must work w/o subproc
868 pydoc.pager = pydoc.plainpager
869 except:
870 sys.stderr = sys.__stderr__
871 raise
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000872 #
David Scherer7aced172000-08-15 01:13:23 +0000873 self.history = self.History(self.text)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000874 #
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000875 self.pollinterval = 50 # millisec
Chui Tey5d2af632002-05-26 13:36:41 +0000876
Kurt B. Kaiser4d5bc602004-06-06 01:29:22 +0000877 def get_standard_extension_names(self):
878 return idleConf.GetExtensions(shell_only=True)
879
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000880 reading = False
881 executing = False
882 canceled = False
883 endoffile = False
884 closing = False
David Scherer7aced172000-08-15 01:13:23 +0000885
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +0000886 def set_warning_stream(self, stream):
Skip Montanarod9161422004-07-06 21:53:27 +0000887 global warning_stream
888 warning_stream = stream
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +0000889
890 def get_warning_stream(self):
891 return warning_stream
892
David Scherer7aced172000-08-15 01:13:23 +0000893 def toggle_debugger(self, event=None):
894 if self.executing:
895 tkMessageBox.showerror("Don't debug now",
896 "You can only toggle the debugger when idle",
897 master=self.text)
898 self.set_debugger_indicator()
899 return "break"
900 else:
901 db = self.interp.getdebugger()
902 if db:
903 self.close_debugger()
904 else:
905 self.open_debugger()
906
907 def set_debugger_indicator(self):
908 db = self.interp.getdebugger()
909 self.setvar("<<toggle-debugger>>", not not db)
910
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000911 def toggle_jit_stack_viewer(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +0000912 pass # All we need is the variable
913
914 def close_debugger(self):
915 db = self.interp.getdebugger()
916 if db:
917 self.interp.setdebugger(None)
918 db.close()
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000919 if self.interp.rpcclt:
920 RemoteDebugger.close_remote_debugger(self.interp.rpcclt)
David Scherer7aced172000-08-15 01:13:23 +0000921 self.resetoutput()
922 self.console.write("[DEBUG OFF]\n")
923 sys.ps1 = ">>> "
924 self.showprompt()
925 self.set_debugger_indicator()
926
927 def open_debugger(self):
Chui Tey5d2af632002-05-26 13:36:41 +0000928 if self.interp.rpcclt:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000929 dbg_gui = RemoteDebugger.start_remote_debugger(self.interp.rpcclt,
930 self)
931 else:
932 dbg_gui = Debugger.Debugger(self)
933 self.interp.setdebugger(dbg_gui)
934 dbg_gui.load_breakpoints()
Chui Tey5d2af632002-05-26 13:36:41 +0000935 sys.ps1 = "[DEBUG ON]\n>>> "
936 self.showprompt()
937 self.set_debugger_indicator()
938
David Scherer7aced172000-08-15 01:13:23 +0000939 def beginexecuting(self):
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000940 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +0000941 self.resetoutput()
942 self.executing = 1
David Scherer7aced172000-08-15 01:13:23 +0000943
944 def endexecuting(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000945 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +0000946 self.executing = 0
947 self.canceled = 0
Chui Tey5d2af632002-05-26 13:36:41 +0000948 self.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000949
950 def close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000951 "Extend EditorWindow.close()"
David Scherer7aced172000-08-15 01:13:23 +0000952 if self.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000953 response = tkMessageBox.askokcancel(
David Scherer7aced172000-08-15 01:13:23 +0000954 "Kill?",
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000955 "The program is still running!\n Do you want to kill it?",
David Scherer7aced172000-08-15 01:13:23 +0000956 default="ok",
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000957 parent=self.text)
Benjamin Peterson2a691a82008-03-31 01:51:45 +0000958 if response is False:
David Scherer7aced172000-08-15 01:13:23 +0000959 return "cancel"
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +0000960 if self.reading:
961 self.top.quit()
962 self.canceled = True
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000963 self.closing = True
964 # Wait for poll_subprocess() rescheduling to stop
965 self.text.after(2 * self.pollinterval, self.close2)
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000966
967 def close2(self):
968 return EditorWindow.close(self)
David Scherer7aced172000-08-15 01:13:23 +0000969
970 def _close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000971 "Extend EditorWindow._close(), shut down debugger and execution server"
David Scherer7aced172000-08-15 01:13:23 +0000972 self.close_debugger()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000973 if use_subprocess:
974 self.interp.kill_subprocess()
David Scherer7aced172000-08-15 01:13:23 +0000975 # Restore std streams
976 sys.stdout = self.save_stdout
977 sys.stderr = self.save_stderr
978 sys.stdin = self.save_stdin
979 # Break cycles
980 self.interp = None
981 self.console = None
David Scherer7aced172000-08-15 01:13:23 +0000982 self.flist.pyshell = None
983 self.history = None
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000984 EditorWindow._close(self)
David Scherer7aced172000-08-15 01:13:23 +0000985
986 def ispythonsource(self, filename):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000987 "Override EditorWindow method: never remove the colorizer"
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000988 return True
David Scherer7aced172000-08-15 01:13:23 +0000989
990 def short_title(self):
991 return self.shell_title
992
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000993 COPYRIGHT = \
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000994 'Type "copyright", "credits" or "license()" for more information.'
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000995
David Scherer7aced172000-08-15 01:13:23 +0000996 def begin(self):
Kurt B. Kaiser7378df72007-08-11 04:20:51 +0000997 self.text.mark_set("iomark", "insert")
David Scherer7aced172000-08-15 01:13:23 +0000998 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000999 if use_subprocess:
1000 nosub = ''
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001001 client = self.interp.start_subprocess()
1002 if not client:
1003 self.close()
Kurt B. Kaiser76637292004-01-21 22:10:01 +00001004 return False
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001005 else:
1006 nosub = "==== No Subprocess ===="
Andrew Svetlovcd49d532012-03-25 11:43:02 +03001007 sys.displayhook = rpc.displayhook
1008
Raymond Hettingera2a8e8b2009-01-27 00:28:36 +00001009 self.write("Python %s on %s\n%s\n%s" %
1010 (sys.version, sys.platform, self.COPYRIGHT, nosub))
David Scherer7aced172000-08-15 01:13:23 +00001011 self.showprompt()
Georg Brandl14fc4272008-05-17 18:39:55 +00001012 import tkinter
1013 tkinter._default_root = None # 03Jan04 KBK What's this?
Kurt B. Kaiser76637292004-01-21 22:10:01 +00001014 return True
David Scherer7aced172000-08-15 01:13:23 +00001015
1016 def readline(self):
1017 save = self.reading
1018 try:
1019 self.reading = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001020 self.top.mainloop() # nested mainloop()
David Scherer7aced172000-08-15 01:13:23 +00001021 finally:
1022 self.reading = save
1023 line = self.text.get("iomark", "end-1c")
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001024 if len(line) == 0: # may be EOF if we quit our mainloop with Ctrl-C
1025 line = "\n"
David Scherer7aced172000-08-15 01:13:23 +00001026 self.resetoutput()
1027 if self.canceled:
1028 self.canceled = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001029 if not use_subprocess:
1030 raise KeyboardInterrupt
David Scherer7aced172000-08-15 01:13:23 +00001031 if self.endoffile:
1032 self.endoffile = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001033 line = ""
David Scherer7aced172000-08-15 01:13:23 +00001034 return line
1035
1036 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001037 return True
David Scherer7aced172000-08-15 01:13:23 +00001038
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001039 def cancel_callback(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +00001040 try:
1041 if self.text.compare("sel.first", "!=", "sel.last"):
1042 return # Active selection -- always use default binding
1043 except:
1044 pass
1045 if not (self.executing or self.reading):
1046 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001047 self.interp.write("KeyboardInterrupt\n")
David Scherer7aced172000-08-15 01:13:23 +00001048 self.showprompt()
1049 return "break"
1050 self.endoffile = 0
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001051 self.canceled = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001052 if (self.executing and self.interp.rpcclt):
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +00001053 if self.interp.getdebugger():
1054 self.interp.restart_subprocess()
1055 else:
1056 self.interp.interrupt_subprocess()
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001057 if self.reading:
1058 self.top.quit() # exit the nested mainloop() in readline()
David Scherer7aced172000-08-15 01:13:23 +00001059 return "break"
1060
1061 def eof_callback(self, event):
1062 if self.executing and not self.reading:
1063 return # Let the default binding (delete next char) take over
1064 if not (self.text.compare("iomark", "==", "insert") and
1065 self.text.compare("insert", "==", "end-1c")):
1066 return # Let the default binding (delete next char) take over
1067 if not self.executing:
David Scherer7aced172000-08-15 01:13:23 +00001068 self.resetoutput()
1069 self.close()
1070 else:
1071 self.canceled = 0
1072 self.endoffile = 1
1073 self.top.quit()
1074 return "break"
1075
David Scherer7aced172000-08-15 01:13:23 +00001076 def linefeed_callback(self, event):
1077 # Insert a linefeed without entering anything (still autoindented)
1078 if self.reading:
1079 self.text.insert("insert", "\n")
1080 self.text.see("insert")
1081 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001082 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001083 return "break"
1084
1085 def enter_callback(self, event):
1086 if self.executing and not self.reading:
1087 return # Let the default binding (insert '\n') take over
1088 # If some text is selected, recall the selection
1089 # (but only if this before the I/O mark)
1090 try:
1091 sel = self.text.get("sel.first", "sel.last")
1092 if sel:
1093 if self.text.compare("sel.last", "<=", "iomark"):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001094 self.recall(sel, event)
David Scherer7aced172000-08-15 01:13:23 +00001095 return "break"
1096 except:
1097 pass
1098 # If we're strictly before the line containing iomark, recall
1099 # the current line, less a leading prompt, less leading or
1100 # trailing whitespace
1101 if self.text.compare("insert", "<", "iomark linestart"):
1102 # Check if there's a relevant stdin range -- if so, use it
1103 prev = self.text.tag_prevrange("stdin", "insert")
1104 if prev and self.text.compare("insert", "<", prev[1]):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001105 self.recall(self.text.get(prev[0], prev[1]), event)
David Scherer7aced172000-08-15 01:13:23 +00001106 return "break"
1107 next = self.text.tag_nextrange("stdin", "insert")
1108 if next and self.text.compare("insert lineend", ">=", next[0]):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001109 self.recall(self.text.get(next[0], next[1]), event)
David Scherer7aced172000-08-15 01:13:23 +00001110 return "break"
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001111 # No stdin mark -- just get the current line, less any prompt
Kurt B. Kaiserb1754452005-11-18 22:05:48 +00001112 indices = self.text.tag_nextrange("console", "insert linestart")
1113 if indices and \
1114 self.text.compare(indices[0], "<=", "insert linestart"):
1115 self.recall(self.text.get(indices[1], "insert lineend"), event)
1116 else:
1117 self.recall(self.text.get("insert linestart", "insert lineend"), event)
David Scherer7aced172000-08-15 01:13:23 +00001118 return "break"
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001119 # If we're between the beginning of the line and the iomark, i.e.
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001120 # in the prompt area, move to the end of the prompt
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001121 if self.text.compare("insert", "<", "iomark"):
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001122 self.text.mark_set("insert", "iomark")
David Scherer7aced172000-08-15 01:13:23 +00001123 # If we're in the current input and there's only whitespace
1124 # beyond the cursor, erase that whitespace first
1125 s = self.text.get("insert", "end-1c")
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001126 if s and not s.strip():
David Scherer7aced172000-08-15 01:13:23 +00001127 self.text.delete("insert", "end-1c")
1128 # If we're in the current input before its last line,
1129 # insert a newline right at the insert point
1130 if self.text.compare("insert", "<", "end-1c linestart"):
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001131 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001132 return "break"
1133 # We're in the last line; append a newline and submit it
1134 self.text.mark_set("insert", "end-1c")
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 self.text.tag_add("stdin", "iomark", "end-1c")
1141 self.text.update_idletasks()
1142 if self.reading:
Neal Norwitzce96f692006-03-17 06:49:51 +00001143 self.top.quit() # Break out of recursive mainloop()
David Scherer7aced172000-08-15 01:13:23 +00001144 else:
1145 self.runit()
1146 return "break"
1147
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001148 def recall(self, s, event):
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001149 # remove leading and trailing empty or whitespace lines
1150 s = re.sub(r'^\s*\n', '' , s)
1151 s = re.sub(r'\n\s*$', '', s)
1152 lines = s.split('\n')
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001153 self.text.undo_block_start()
1154 try:
1155 self.text.tag_remove("sel", "1.0", "end")
1156 self.text.mark_set("insert", "end-1c")
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001157 prefix = self.text.get("insert linestart", "insert")
1158 if prefix.rstrip().endswith(':'):
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001159 self.newline_and_indent_event(event)
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001160 prefix = self.text.get("insert linestart", "insert")
1161 self.text.insert("insert", lines[0].strip())
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001162 if len(lines) > 1:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001163 orig_base_indent = re.search(r'^([ \t]*)', lines[0]).group(0)
1164 new_base_indent = re.search(r'^([ \t]*)', prefix).group(0)
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001165 for line in lines[1:]:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001166 if line.startswith(orig_base_indent):
1167 # replace orig base indentation with new indentation
1168 line = new_base_indent + line[len(orig_base_indent):]
1169 self.text.insert('insert', '\n'+line.rstrip())
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001170 finally:
1171 self.text.see("insert")
1172 self.text.undo_block_stop()
David Scherer7aced172000-08-15 01:13:23 +00001173
1174 def runit(self):
1175 line = self.text.get("iomark", "end-1c")
1176 # Strip off last newline and surrounding whitespace.
1177 # (To allow you to hit return twice to end a statement.)
1178 i = len(line)
1179 while i > 0 and line[i-1] in " \t":
1180 i = i-1
1181 if i > 0 and line[i-1] == "\n":
1182 i = i-1
1183 while i > 0 and line[i-1] in " \t":
1184 i = i-1
1185 line = line[:i]
1186 more = self.interp.runsource(line)
David Scherer7aced172000-08-15 01:13:23 +00001187
David Scherer7aced172000-08-15 01:13:23 +00001188 def open_stack_viewer(self, event=None):
Chui Tey5d2af632002-05-26 13:36:41 +00001189 if self.interp.rpcclt:
1190 return self.interp.remote_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +00001191 try:
1192 sys.last_traceback
1193 except:
1194 tkMessageBox.showerror("No stack trace",
1195 "There is no stack trace yet.\n"
1196 "(sys.last_traceback is not defined)",
1197 master=self.text)
1198 return
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +00001199 from idlelib.StackViewer import StackBrowser
David Scherer7aced172000-08-15 01:13:23 +00001200 sv = StackBrowser(self.root, self.flist)
1201
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001202 def view_restart_mark(self, event=None):
1203 self.text.see("iomark")
1204 self.text.see("restart")
1205
1206 def restart_shell(self, event=None):
Terry Jan Reedyda4c4672012-01-31 02:26:32 -05001207 "Callback for Run/Restart Shell Cntl-F6"
1208 self.interp.restart_subprocess(with_cwd=True)
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001209
David Scherer7aced172000-08-15 01:13:23 +00001210 def showprompt(self):
1211 self.resetoutput()
1212 try:
1213 s = str(sys.ps1)
1214 except:
1215 s = ""
1216 self.console.write(s)
1217 self.text.mark_set("insert", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001218 self.set_line_and_column()
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +00001219 self.io.reset_undo()
David Scherer7aced172000-08-15 01:13:23 +00001220
1221 def resetoutput(self):
1222 source = self.text.get("iomark", "end-1c")
1223 if self.history:
1224 self.history.history_store(source)
1225 if self.text.get("end-2c") != "\n":
1226 self.text.insert("end-1c", "\n")
1227 self.text.mark_set("iomark", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001228 self.set_line_and_column()
David Scherer7aced172000-08-15 01:13:23 +00001229
1230 def write(self, s, tags=()):
Andrew Svetlov05bab932012-03-14 13:22:12 -07001231 if isinstance(s, str) and len(s) and max(s) > '\uffff':
1232 # Tk doesn't support outputting non-BMP characters
1233 # Let's assume what printed string is not very long,
1234 # find first non-BMP character and construct informative
1235 # UnicodeEncodeError exception.
1236 for start, char in enumerate(s):
1237 if char > '\uffff':
1238 break
1239 raise UnicodeEncodeError("UCS-2", char, start, start+1,
1240 'Non-BMP character not supported in Tk')
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001241 try:
1242 self.text.mark_gravity("iomark", "right")
1243 OutputWindow.write(self, s, tags, "iomark")
1244 self.text.mark_gravity("iomark", "left")
1245 except:
Kurt B. Kaisercbbe98f2007-08-12 01:52:35 +00001246 raise ###pass # ### 11Aug07 KBK if we are expecting exceptions
1247 # let's find out what they are and be specific.
David Scherer7aced172000-08-15 01:13:23 +00001248 if self.canceled:
1249 self.canceled = 0
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001250 if not use_subprocess:
1251 raise KeyboardInterrupt
David Scherer7aced172000-08-15 01:13:23 +00001252
Kurt B. Kaiserdcba6622004-12-21 22:10:32 +00001253class PseudoFile(object):
David Scherer7aced172000-08-15 01:13:23 +00001254
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001255 def __init__(self, shell, tags, encoding=None):
David Scherer7aced172000-08-15 01:13:23 +00001256 self.shell = shell
1257 self.tags = tags
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001258 self.encoding = encoding
David Scherer7aced172000-08-15 01:13:23 +00001259
1260 def write(self, s):
1261 self.shell.write(s, self.tags)
1262
Kurt B. Kaiser66aaf742007-08-09 18:00:23 +00001263 def writelines(self, lines):
1264 for line in lines:
1265 self.write(line)
David Scherer7aced172000-08-15 01:13:23 +00001266
1267 def flush(self):
1268 pass
1269
1270 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001271 return True
David Scherer7aced172000-08-15 01:13:23 +00001272
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001273
David Scherer7aced172000-08-15 01:13:23 +00001274usage_msg = """\
David Scherer7aced172000-08-15 01:13:23 +00001275
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001276USAGE: idle [-deins] [-t title] [file]*
1277 idle [-dns] [-t title] (-c cmd | -r file) [arg]*
1278 idle [-dns] [-t title] - [arg]*
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001279
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001280 -h print this help message and exit
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001281 -n run IDLE without a subprocess (see Help/IDLE Help for details)
David Scherer7aced172000-08-15 01:13:23 +00001282
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001283The following options will override the IDLE 'settings' configuration:
Kurt B. Kaiser96d88422001-07-17 04:59:01 +00001284
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001285 -e open an edit window
1286 -i open a shell window
1287
1288The following options imply -i and will open a shell:
1289
1290 -c cmd run the command in a shell, or
1291 -r file run script from file
1292
1293 -d enable the debugger
1294 -s run $IDLESTARTUP or $PYTHONSTARTUP before anything else
1295 -t title set title of shell window
1296
1297A default edit window will be bypassed when -c, -r, or - are used.
1298
1299[arg]* are passed to the command (-c) or script (-r) in sys.argv[1:].
1300
1301Examples:
1302
1303idle
1304 Open an edit window or shell depending on IDLE's configuration.
1305
1306idle foo.py foobar.py
1307 Edit the files, also open a shell if configured to start with shell.
1308
1309idle -est "Baz" foo.py
1310 Run $IDLESTARTUP or $PYTHONSTARTUP, edit foo.py, and open a shell
1311 window with the title "Baz".
1312
Neal Norwitz752abd02008-05-13 04:55:24 +00001313idle -c "import sys; print(sys.argv)" "foo"
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001314 Open a shell window and run the command, passing "-c" in sys.argv[0]
1315 and "foo" in sys.argv[1].
1316
1317idle -d -s -r foo.py "Hello World"
1318 Open a shell window, run a startup script, enable the debugger, and
1319 run foo.py, passing "foo.py" in sys.argv[0] and "Hello World" in
1320 sys.argv[1].
1321
Neal Norwitz752abd02008-05-13 04:55:24 +00001322echo "import sys; print(sys.argv)" | idle - "foobar"
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001323 Open a shell window, run the script piped in, passing '' in sys.argv[0]
1324 and "foobar" in sys.argv[1].
David Scherer7aced172000-08-15 01:13:23 +00001325"""
1326
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001327def main():
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001328 global flist, root, use_subprocess
David Scherer7aced172000-08-15 01:13:23 +00001329
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001330 use_subprocess = True
Kurt B. Kaisere866c812009-04-04 21:07:39 +00001331 enable_shell = True
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001332 enable_edit = False
1333 debug = False
1334 cmd = None
1335 script = None
1336 startup = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001337 try:
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001338 opts, args = getopt.getopt(sys.argv[1:], "c:deihnr:st:")
Guido van Rossumb940e112007-01-10 16:19:56 +00001339 except getopt.error as msg:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001340 sys.stderr.write("Error: %s\n" % str(msg))
1341 sys.stderr.write(usage_msg)
1342 sys.exit(2)
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001343 for o, a in opts:
1344 if o == '-c':
1345 cmd = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001346 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001347 if o == '-d':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001348 debug = True
1349 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001350 if o == '-e':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001351 enable_edit = True
Kurt B. Kaisere866c812009-04-04 21:07:39 +00001352 enable_shell = False
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001353 if o == '-h':
1354 sys.stdout.write(usage_msg)
1355 sys.exit()
1356 if o == '-i':
1357 enable_shell = True
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001358 if o == '-n':
1359 use_subprocess = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001360 if o == '-r':
1361 script = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001362 if os.path.isfile(script):
1363 pass
1364 else:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001365 print("No script file: ", script)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001366 sys.exit()
1367 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001368 if o == '-s':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001369 startup = True
1370 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001371 if o == '-t':
1372 PyShell.shell_title = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001373 enable_shell = True
1374 if args and args[0] == '-':
1375 cmd = sys.stdin.read()
1376 enable_shell = True
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001377 # process sys.argv and sys.path:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001378 for i in range(len(sys.path)):
1379 sys.path[i] = os.path.abspath(sys.path[i])
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001380 if args and args[0] == '-':
1381 sys.argv = [''] + args[1:]
1382 elif cmd:
1383 sys.argv = ['-c'] + args
1384 elif script:
1385 sys.argv = [script] + args
1386 elif args:
1387 enable_edit = True
1388 pathx = []
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001389 for filename in args:
1390 pathx.append(os.path.dirname(filename))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001391 for dir in pathx:
1392 dir = os.path.abspath(dir)
1393 if not dir in sys.path:
1394 sys.path.insert(0, dir)
Kurt B. Kaiserff002b92002-12-21 21:39:11 +00001395 else:
Neal Norwitzd082b6e2007-08-26 23:37:53 +00001396 dir = os.getcwd()
1397 if dir not in sys.path:
Kurt B. Kaiserff002b92002-12-21 21:39:11 +00001398 sys.path.insert(0, dir)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001399 # check the IDLE settings configuration (but command line overrides)
1400 edit_start = idleConf.GetOption('main', 'General',
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001401 'editor-on-startup', type='bool')
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001402 enable_edit = enable_edit or edit_start
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001403 # start editor and/or shell windows:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001404 root = Tk(className="Idle")
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001405
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001406 fixwordbreaks(root)
1407 root.withdraw()
1408 flist = PyShellFileList(root)
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001409 macosxSupport.setupApp(root, flist)
1410
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001411 if enable_edit:
1412 if not (cmd or script):
Andrew Svetlov6b6e4372012-03-20 23:03:26 +02001413 for filename in args[:]:
1414 if flist.open(filename) is None:
1415 # filename is a directory actually, disconsider it
1416 args.remove(filename)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001417 if not args:
1418 flist.new()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001419 if enable_shell:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001420 shell = flist.open_shell()
1421 if not shell:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001422 return # couldn't open shell
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001423
1424 if macosxSupport.runningAsOSXApp() and flist.dict:
1425 # On OSX: when the user has double-clicked on a file that causes
1426 # IDLE to be launched the shell window will open just in front of
1427 # the file she wants to see. Lower the interpreter window when
1428 # there are open files.
1429 shell.top.lower()
1430
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001431 shell = flist.pyshell
1432 # handle remaining options:
1433 if debug:
1434 shell.open_debugger()
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001435 if startup:
1436 filename = os.environ.get("IDLESTARTUP") or \
1437 os.environ.get("PYTHONSTARTUP")
1438 if filename and os.path.isfile(filename):
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001439 shell.interp.execfile(filename)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001440 if shell and cmd or script:
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001441 shell.interp.runcommand("""if 1:
1442 import sys as _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001443 _sys.argv = %r
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001444 del _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001445 \n""" % (sys.argv,))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001446 if cmd:
1447 shell.interp.execsource(cmd)
1448 elif script:
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001449 shell.interp.prepend_syspath(script)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001450 shell.interp.execfile(script)
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001451
Ned Deily4ce92b22011-01-15 04:37:12 +00001452 # Check for problematic OS X Tk versions and print a warning message
1453 # in the IDLE shell window; this is less intrusive than always opening
1454 # a separate window.
1455 tkversionwarning = macosxSupport.tkVersionWarning(root)
1456 if tkversionwarning:
1457 shell.interp.runcommand(''.join(("print('", tkversionwarning, "')")))
1458
Terry Jan Reedycd6b8c62012-05-26 20:23:45 -04001459 while flist.inversedict: # keep IDLE running while files are open.
1460 root.mainloop()
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001461 root.destroy()
1462
David Scherer7aced172000-08-15 01:13:23 +00001463if __name__ == "__main__":
Kurt B. Kaiser9e8b8282003-06-15 17:38:45 +00001464 sys.modules['PyShell'] = sys.modules['__main__']
David Scherer7aced172000-08-15 01:13:23 +00001465 main()