blob: 15ca392ca249ca3af1548bb5528cb66390838b68 [file] [log] [blame]
David Scherer7aced172000-08-15 01:13:23 +00001#! /usr/bin/env python
2
David Scherer7aced172000-08-15 01:13:23 +00003import os
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +00004import os.path
David Scherer7aced172000-08-15 01:13:23 +00005import sys
6import string
7import getopt
8import re
Chui Tey5d2af632002-05-26 13:36:41 +00009import socket
10import time
Kurt B. Kaiser003091c2003-02-17 18:57:16 +000011import threading
Chui Tey5d2af632002-05-26 13:36:41 +000012import traceback
Kurt B. Kaiser62833982002-09-18 17:07:05 +000013import types
Martin v. Löwise2b56242012-07-25 10:56:22 +020014import io
David Scherer7aced172000-08-15 01:13:23 +000015
16import linecache
17from code import InteractiveInterpreter
18
Kurt B. Kaiser2303b1c2003-11-24 05:26:16 +000019try:
Georg Brandl6634bf22008-05-20 07:13:37 +000020 from Tkinter import *
Kurt B. Kaiser2303b1c2003-11-24 05:26:16 +000021except ImportError:
Georg Brandl6634bf22008-05-20 07:13:37 +000022 print>>sys.__stderr__, "** IDLE can't import Tkinter. " \
Kurt B. Kaiser2303b1c2003-11-24 05:26:16 +000023 "Your Python may not be configured for Tk. **"
24 sys.exit(1)
Georg Brandl6634bf22008-05-20 07:13:37 +000025import tkMessageBox
David Scherer7aced172000-08-15 01:13:23 +000026
Florent Xiclunad630c042010-04-02 07:24:52 +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. Kaiserb9764192002-09-23 04:10:37 +000039IDENTCHARS = string.ascii_letters + string.digits + "_"
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +000040HOST = '127.0.0.1' # python execution server on localhost loopback
41PORT = 0 # someday pass in host, port for remote debug capability
Kurt B. Kaiserb9764192002-09-23 04:10:37 +000042
Kurt B. Kaisera00050f2003-05-08 20:26:55 +000043try:
44 from signal import SIGTERM
45except ImportError:
46 SIGTERM = 15
47
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000048# Override warnings module to write to warning_stream. Initialize to send IDLE
49# internal warnings to the console. ScriptBinding.check_syntax() will
50# temporarily redirect the stream to the shell window to display warnings when
51# checking user's code.
52global warning_stream
53warning_stream = sys.__stderr__
Chui Tey5d2af632002-05-26 13:36:41 +000054try:
55 import warnings
56except ImportError:
57 pass
58else:
Benjamin Petersonb76444b2008-10-16 19:40:14 +000059 def idle_showwarning(message, category, filename, lineno,
60 file=None, line=None):
Guilherme Polof198ac22009-08-14 14:03:07 +000061 if file is None:
62 file = warning_stream
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000063 try:
Guilherme Polof198ac22009-08-14 14:03:07 +000064 file.write(warnings.formatwarning(message, category, filename,
Senthil Kumaran13502b12011-07-03 17:38:53 -070065 lineno, line=line))
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000066 except IOError:
67 pass ## file (probably __stderr__) is invalid, warning dropped.
Chui Tey5d2af632002-05-26 13:36:41 +000068 warnings.showwarning = idle_showwarning
Guilherme Polof198ac22009-08-14 14:03:07 +000069 def idle_formatwarning(message, category, filename, lineno, line=None):
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000070 """Format warnings the IDLE way"""
71 s = "\nWarning (from warnings module):\n"
72 s += ' File \"%s\", line %s\n' % (filename, lineno)
Guilherme Polof198ac22009-08-14 14:03:07 +000073 if line is None:
74 line = linecache.getline(filename, lineno)
75 line = line.strip()
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000076 if line:
77 s += " %s\n" % line
78 s += "%s: %s\n>>> " % (category.__name__, message)
79 return s
80 warnings.formatwarning = idle_formatwarning
Chui Tey5d2af632002-05-26 13:36:41 +000081
Kurt B. Kaiserf7a88992004-11-13 21:05:58 +000082def extended_linecache_checkcache(filename=None,
83 orig_checkcache=linecache.checkcache):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +000084 """Extend linecache.checkcache to preserve the <pyshell#...> entries
85
Kurt B. Kaiserf7a88992004-11-13 21:05:58 +000086 Rather than repeating the linecache code, patch it to save the
87 <pyshell#...> entries, call the original linecache.checkcache()
Guilherme Polof198ac22009-08-14 14:03:07 +000088 (skipping them), and then restore the saved entries.
Kurt B. Kaiserf7a88992004-11-13 21:05:58 +000089
90 orig_checkcache is bound at definition time to the original
91 method, allowing it to be patched.
Kurt B. Kaiser45186c42002-10-23 04:48:08 +000092 """
David Scherer7aced172000-08-15 01:13:23 +000093 cache = linecache.cache
94 save = {}
Guilherme Polof198ac22009-08-14 14:03:07 +000095 for key in list(cache):
96 if key[:1] + key[-1:] == '<>':
97 save[key] = cache.pop(key)
98 orig_checkcache(filename)
David Scherer7aced172000-08-15 01:13:23 +000099 cache.update(save)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000100
Kurt B. Kaiser81885592002-11-29 22:10:53 +0000101# Patch linecache.checkcache():
102linecache.checkcache = extended_linecache_checkcache
David Scherer7aced172000-08-15 01:13:23 +0000103
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000104
David Scherer7aced172000-08-15 01:13:23 +0000105class PyShellEditorWindow(EditorWindow):
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000106 "Regular text edit window in IDLE, supports breakpoints"
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000107
David Scherer7aced172000-08-15 01:13:23 +0000108 def __init__(self, *args):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000109 self.breakpoints = []
Raymond Hettinger931237e2003-07-09 18:48:24 +0000110 EditorWindow.__init__(self, *args)
David Scherer7aced172000-08-15 01:13:23 +0000111 self.text.bind("<<set-breakpoint-here>>", self.set_breakpoint_here)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000112 self.text.bind("<<clear-breakpoint-here>>", self.clear_breakpoint_here)
David Scherer7aced172000-08-15 01:13:23 +0000113 self.text.bind("<<open-python-shell>>", self.flist.open_shell)
114
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000115 self.breakpointPath = os.path.join(idleConf.GetUserCfgDir(),
116 'breakpoints.lst')
Chui Teya2adb0f2002-11-04 22:14:54 +0000117 # whenever a file is changed, restore breakpoints
118 if self.io.filename: self.restore_file_breaks()
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000119 def filename_changed_hook(old_hook=self.io.filename_change_hook,
120 self=self):
Chui Teya2adb0f2002-11-04 22:14:54 +0000121 self.restore_file_breaks()
122 old_hook()
123 self.io.set_filename_change_hook(filename_changed_hook)
124
Andrew Svetlov5018db72012-11-01 22:39:14 +0200125 rmenu_specs = [
126 ("Cut", "<<cut>>", "rmenu_check_cut"),
127 ("Copy", "<<copy>>", "rmenu_check_copy"),
128 ("Paste", "<<paste>>", "rmenu_check_paste"),
129 ("Set Breakpoint", "<<set-breakpoint-here>>", None),
130 ("Clear Breakpoint", "<<clear-breakpoint-here>>", None)
131 ]
David Scherer7aced172000-08-15 01:13:23 +0000132
Chui Teya2adb0f2002-11-04 22:14:54 +0000133 def set_breakpoint(self, lineno):
134 text = self.text
135 filename = self.io.filename
136 text.tag_add("BREAK", "%d.0" % lineno, "%d.0" % (lineno+1))
137 try:
138 i = self.breakpoints.index(lineno)
139 except ValueError: # only add if missing, i.e. do once
140 self.breakpoints.append(lineno)
141 try: # update the subprocess debugger
142 debug = self.flist.pyshell.interp.debugger
143 debug.set_breakpoint_here(filename, lineno)
144 except: # but debugger may not be active right now....
145 pass
146
David Scherer7aced172000-08-15 01:13:23 +0000147 def set_breakpoint_here(self, event=None):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000148 text = self.text
149 filename = self.io.filename
150 if not filename:
151 text.bell()
David Scherer7aced172000-08-15 01:13:23 +0000152 return
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000153 lineno = int(float(text.index("insert")))
Chui Teya2adb0f2002-11-04 22:14:54 +0000154 self.set_breakpoint(lineno)
David Scherer7aced172000-08-15 01:13:23 +0000155
Kurt B. Kaiser669f4c32002-06-20 04:01:47 +0000156 def clear_breakpoint_here(self, event=None):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000157 text = self.text
158 filename = self.io.filename
159 if not filename:
160 text.bell()
Kurt B. Kaiser669f4c32002-06-20 04:01:47 +0000161 return
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000162 lineno = int(float(text.index("insert")))
163 try:
164 self.breakpoints.remove(lineno)
165 except:
166 pass
167 text.tag_remove("BREAK", "insert linestart",\
168 "insert lineend +1char")
169 try:
170 debug = self.flist.pyshell.interp.debugger
171 debug.clear_breakpoint_here(filename, lineno)
172 except:
173 pass
174
175 def clear_file_breaks(self):
176 if self.breakpoints:
177 text = self.text
178 filename = self.io.filename
179 if not filename:
180 text.bell()
181 return
182 self.breakpoints = []
183 text.tag_remove("BREAK", "1.0", END)
184 try:
185 debug = self.flist.pyshell.interp.debugger
186 debug.clear_file_breaks(filename)
187 except:
188 pass
189
Chui Teya2adb0f2002-11-04 22:14:54 +0000190 def store_file_breaks(self):
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000191 "Save breakpoints when file is saved"
192 # XXX 13 Dec 2002 KBK Currently the file must be saved before it can
193 # be run. The breaks are saved at that time. If we introduce
194 # a temporary file save feature the save breaks functionality
195 # needs to be re-verified, since the breaks at the time the
196 # temp file is created may differ from the breaks at the last
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000197 # permanent save of the file. Currently, a break introduced
198 # after a save will be effective, but not persistent.
199 # This is necessary to keep the saved breaks synched with the
200 # saved file.
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000201 #
202 # Breakpoints are set as tagged ranges in the text. Certain
203 # kinds of edits cause these ranges to be deleted: Inserting
204 # or deleting a line just before a breakpoint, and certain
205 # deletions prior to a breakpoint. These issues need to be
206 # investigated and understood. It's not clear if they are
207 # Tk issues or IDLE issues, or whether they can actually
208 # be fixed. Since a modified file has to be saved before it is
209 # run, and since self.breakpoints (from which the subprocess
210 # debugger is loaded) is updated during the save, the visible
211 # breaks stay synched with the subprocess even if one of these
212 # unexpected breakpoint deletions occurs.
213 breaks = self.breakpoints
214 filename = self.io.filename
Chui Teya2adb0f2002-11-04 22:14:54 +0000215 try:
Ned Deily40ad0412011-12-14 14:57:43 -0800216 with open(self.breakpointPath,"r") as old_file:
217 lines = old_file.readlines()
Chui Teya2adb0f2002-11-04 22:14:54 +0000218 except IOError:
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000219 lines = []
Ned Deily40ad0412011-12-14 14:57:43 -0800220 try:
221 with open(self.breakpointPath,"w") as new_file:
222 for line in lines:
223 if not line.startswith(filename + '='):
224 new_file.write(line)
225 self.update_breakpoints()
226 breaks = self.breakpoints
227 if breaks:
228 new_file.write(filename + '=' + str(breaks) + '\n')
229 except IOError as err:
230 if not getattr(self.root, "breakpoint_error_displayed", False):
231 self.root.breakpoint_error_displayed = True
232 tkMessageBox.showerror(title='IDLE Error',
233 message='Unable to update breakpoint list:\n%s'
234 % str(err),
235 parent=self.text)
Chui Teya2adb0f2002-11-04 22:14:54 +0000236
237 def restore_file_breaks(self):
238 self.text.update() # this enables setting "BREAK" tags to be visible
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000239 filename = self.io.filename
240 if filename is None:
241 return
Chui Tey69371d62002-11-04 23:39:45 +0000242 if os.path.isfile(self.breakpointPath):
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000243 lines = open(self.breakpointPath,"r").readlines()
Chui Tey69371d62002-11-04 23:39:45 +0000244 for line in lines:
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000245 if line.startswith(filename + '='):
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000246 breakpoint_linenumbers = eval(line[len(filename)+1:])
Chui Tey69371d62002-11-04 23:39:45 +0000247 for breakpoint_linenumber in breakpoint_linenumbers:
248 self.set_breakpoint(breakpoint_linenumber)
Chui Teya2adb0f2002-11-04 22:14:54 +0000249
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000250 def update_breakpoints(self):
251 "Retrieves all the breakpoints in the current window"
Chui Teya2adb0f2002-11-04 22:14:54 +0000252 text = self.text
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000253 ranges = text.tag_ranges("BREAK")
254 linenumber_list = self.ranges_to_linenumbers(ranges)
255 self.breakpoints = linenumber_list
256
257 def ranges_to_linenumbers(self, ranges):
258 lines = []
259 for index in range(0, len(ranges), 2):
Andrew Svetlov8a15c372012-07-31 19:51:27 +0300260 lineno = int(float(ranges[index].string))
261 end = int(float(ranges[index+1].string))
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000262 while lineno < end:
263 lines.append(lineno)
264 lineno += 1
265 return lines
266
Kurt B. Kaiser11220fa2002-12-24 00:57:22 +0000267# XXX 13 Dec 2002 KBK Not used currently
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000268# def saved_change_hook(self):
269# "Extend base method - clear breaks if module is modified"
270# if not self.get_saved():
271# self.clear_file_breaks()
272# EditorWindow.saved_change_hook(self)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000273
274 def _close(self):
275 "Extend base method - clear breaks when module is closed"
276 self.clear_file_breaks()
277 EditorWindow._close(self)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000278
David Scherer7aced172000-08-15 01:13:23 +0000279
280class PyShellFileList(FileList):
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000281 "Extend base class: IDLE supports a shell and breakpoints"
David Scherer7aced172000-08-15 01:13:23 +0000282
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000283 # override FileList's class variable, instances return PyShellEditorWindow
284 # instead of EditorWindow when new edit windows are created.
David Scherer7aced172000-08-15 01:13:23 +0000285 EditorWindow = PyShellEditorWindow
286
287 pyshell = None
288
289 def open_shell(self, event=None):
290 if self.pyshell:
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000291 self.pyshell.top.wakeup()
David Scherer7aced172000-08-15 01:13:23 +0000292 else:
293 self.pyshell = PyShell(self)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000294 if self.pyshell:
295 if not self.pyshell.begin():
296 return None
David Scherer7aced172000-08-15 01:13:23 +0000297 return self.pyshell
298
299
300class ModifiedColorDelegator(ColorDelegator):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000301 "Extend base class: colorizer for the shell window itself"
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000302
Steven M. Gavab77d3432002-03-02 07:16:21 +0000303 def __init__(self):
304 ColorDelegator.__init__(self)
305 self.LoadTagDefs()
David Scherer7aced172000-08-15 01:13:23 +0000306
307 def recolorize_main(self):
308 self.tag_remove("TODO", "1.0", "iomark")
309 self.tag_add("SYNC", "1.0", "iomark")
310 ColorDelegator.recolorize_main(self)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000311
Steven M. Gavab77d3432002-03-02 07:16:21 +0000312 def LoadTagDefs(self):
313 ColorDelegator.LoadTagDefs(self)
314 theme = idleConf.GetOption('main','Theme','name')
315 self.tagdefs.update({
316 "stdin": {'background':None,'foreground':None},
317 "stdout": idleConf.GetHighlight(theme, "stdout"),
318 "stderr": idleConf.GetHighlight(theme, "stderr"),
319 "console": idleConf.GetHighlight(theme, "console"),
Steven M. Gavab77d3432002-03-02 07:16:21 +0000320 })
David Scherer7aced172000-08-15 01:13:23 +0000321
Ned Deily5e247b72012-05-31 09:17:29 -0700322 def removecolors(self):
323 # Don't remove shell color tags before "iomark"
324 for tag in self.tagdefs:
325 self.tag_remove(tag, "iomark", "end")
326
David Scherer7aced172000-08-15 01:13:23 +0000327class ModifiedUndoDelegator(UndoDelegator):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000328 "Extend base class: forbid insert/delete before the I/O mark"
David Scherer7aced172000-08-15 01:13:23 +0000329
330 def insert(self, index, chars, tags=None):
331 try:
332 if self.delegate.compare(index, "<", "iomark"):
333 self.delegate.bell()
334 return
335 except TclError:
336 pass
337 UndoDelegator.insert(self, index, chars, tags)
338
339 def delete(self, index1, index2=None):
340 try:
341 if self.delegate.compare(index1, "<", "iomark"):
342 self.delegate.bell()
343 return
344 except TclError:
345 pass
346 UndoDelegator.delete(self, index1, index2)
347
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000348
349class MyRPCClient(rpc.RPCClient):
350
351 def handle_EOF(self):
352 "Override the base class - just re-raise EOFError"
353 raise EOFError
354
Kurt B. Kaiser8d1f11b2003-05-26 22:20:34 +0000355
David Scherer7aced172000-08-15 01:13:23 +0000356class ModifiedInterpreter(InteractiveInterpreter):
357
358 def __init__(self, tkconsole):
359 self.tkconsole = tkconsole
360 locals = sys.modules['__main__'].__dict__
361 InteractiveInterpreter.__init__(self, locals=locals)
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000362 self.save_warnings_filters = None
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000363 self.restarting = False
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +0000364 self.subprocess_arglist = None
365 self.port = PORT
Ned Deily86d669b2011-10-30 19:58:04 -0700366 self.original_compiler_flags = self.compile.compiler.flags
David Scherer7aced172000-08-15 01:13:23 +0000367
Chui Tey5d2af632002-05-26 13:36:41 +0000368 rpcclt = None
369 rpcpid = None
370
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000371 def spawn_subprocess(self):
Florent Xiclunac8a730b2010-03-25 20:32:07 +0000372 if self.subprocess_arglist is None:
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +0000373 self.subprocess_arglist = self.build_subprocess_arglist()
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000374 args = self.subprocess_arglist
Kurt B. Kaiserb7855182003-08-14 14:54:28 +0000375 self.rpcpid = os.spawnv(os.P_NOWAIT, sys.executable, args)
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000376
Tony Lowndsf53dec22002-12-20 04:24:43 +0000377 def build_subprocess_arglist(self):
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +0000378 assert (self.port!=0), (
379 "Socket should have been assigned a port number.")
Tony Lownds2398d572003-05-13 15:28:21 +0000380 w = ['-W' + s for s in sys.warnoptions]
Georg Brandld0761532006-10-12 07:57:21 +0000381 if 1/2 > 0: # account for new division
382 w.append('-Qnew')
Tony Lownds2398d572003-05-13 15:28:21 +0000383 # Maybe IDLE is installed and is being accessed via sys.path,
384 # or maybe it's not installed and the idle.py script is being
385 # run from the IDLE source directory.
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000386 del_exitf = idleConf.GetOption('main', 'General', 'delete-exitfunc',
387 default=False, type='bool')
Tony Lownds2398d572003-05-13 15:28:21 +0000388 if __name__ == 'idlelib.PyShell':
Walter Dörwald70a6b492004-02-12 17:35:32 +0000389 command = "__import__('idlelib.run').run.main(%r)" % (del_exitf,)
Tony Lowndsf2324b92002-09-29 00:34:10 +0000390 else:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000391 command = "__import__('run').main(%r)" % (del_exitf,)
Kurt B. Kaiserb7855182003-08-14 14:54:28 +0000392 if sys.platform[:3] == 'win' and ' ' in sys.executable:
393 # handle embedded space in path by quoting the argument
394 decorated_exec = '"%s"' % sys.executable
395 else:
396 decorated_exec = sys.executable
397 return [decorated_exec] + w + ["-c", command, str(self.port)]
Tony Lowndsf2324b92002-09-29 00:34:10 +0000398
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000399 def start_subprocess(self):
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +0000400 addr = (HOST, self.port)
401 # GUI makes several attempts to acquire socket, listens for connection
Kurt B. Kaiser5db48432003-05-15 03:40:51 +0000402 for i in range(3):
Chui Tey5d2af632002-05-26 13:36:41 +0000403 time.sleep(i)
404 try:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000405 self.rpcclt = MyRPCClient(addr)
Chui Tey5d2af632002-05-26 13:36:41 +0000406 break
407 except socket.error, err:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000408 pass
Chui Tey5d2af632002-05-26 13:36:41 +0000409 else:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000410 self.display_port_binding_error()
411 return None
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +0000412 # if PORT was 0, system will assign an 'ephemeral' port. Find it out:
413 self.port = self.rpcclt.listening_sock.getsockname()[1]
414 # if PORT was not 0, probably working with a remote execution server
415 if PORT != 0:
416 # To allow reconnection within the 2MSL wait (cf. Stevens TCP
417 # V1, 18.6), set SO_REUSEADDR. Note that this can be problematic
418 # on Windows since the implementation allows two active sockets on
419 # the same address!
420 self.rpcclt.listening_sock.setsockopt(socket.SOL_SOCKET,
421 socket.SO_REUSEADDR, 1)
422 self.spawn_subprocess()
423 #time.sleep(20) # test to simulate GUI not accepting connection
Kurt B. Kaiserb4179362002-07-26 00:06:42 +0000424 # Accept the connection from the Python execution server
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000425 self.rpcclt.listening_sock.settimeout(10)
426 try:
427 self.rpcclt.accept()
428 except socket.timeout, err:
429 self.display_no_subprocess_error()
430 return None
Martin v. Löwise2b56242012-07-25 10:56:22 +0200431 # Can't regiter self.tkconsole.stdin, since run.py wants to
432 # call non-TextIO methods on it (such as getvar)
433 # XXX should be renamed to "console"
Kurt B. Kaiser969de452002-06-12 03:28:57 +0000434 self.rpcclt.register("stdin", self.tkconsole)
435 self.rpcclt.register("stdout", self.tkconsole.stdout)
436 self.rpcclt.register("stderr", self.tkconsole.stderr)
Chui Tey5d2af632002-05-26 13:36:41 +0000437 self.rpcclt.register("flist", self.tkconsole.flist)
Kurt B. Kaiser8cd0def2003-01-31 05:06:43 +0000438 self.rpcclt.register("linecache", linecache)
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000439 self.rpcclt.register("interp", self)
Terry Jan Reedyb98000a2012-01-31 02:09:25 -0500440 self.transfer_path(with_cwd=True)
Chui Tey5d2af632002-05-26 13:36:41 +0000441 self.poll_subprocess()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000442 return self.rpcclt
Chui Tey5d2af632002-05-26 13:36:41 +0000443
Terry Jan Reedyb98000a2012-01-31 02:09:25 -0500444 def restart_subprocess(self, with_cwd=False):
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000445 if self.restarting:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000446 return self.rpcclt
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000447 self.restarting = True
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000448 # close only the subprocess debugger
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000449 debug = self.getdebugger()
450 if debug:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000451 try:
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000452 # Only close subprocess debugger, don't unregister gui_adap!
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000453 RemoteDebugger.close_subprocess_debugger(self.rpcclt)
454 except:
455 pass
456 # Kill subprocess, spawn a new one, accept connection.
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000457 self.rpcclt.close()
458 self.unix_terminate()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000459 console = self.tkconsole
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000460 was_executing = console.executing
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000461 console.executing = False
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000462 self.spawn_subprocess()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000463 try:
464 self.rpcclt.accept()
465 except socket.timeout, err:
466 self.display_no_subprocess_error()
467 return None
Terry Jan Reedyb98000a2012-01-31 02:09:25 -0500468 self.transfer_path(with_cwd=with_cwd)
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000469 # annotate restart in shell window and mark it
Kurt B. Kaiser4cc5ef52003-01-22 00:23:23 +0000470 console.text.delete("iomark", "end-1c")
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000471 if was_executing:
472 console.write('\n')
473 console.showprompt()
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000474 halfbar = ((int(console.width) - 16) // 2) * '='
475 console.write(halfbar + ' RESTART ' + halfbar)
476 console.text.mark_set("restart", "end-1c")
477 console.text.mark_gravity("restart", "left")
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000478 console.showprompt()
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000479 # restart subprocess debugger
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000480 if debug:
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000481 # Restarted debugger connects to current instance of debug GUI
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000482 gui = RemoteDebugger.restart_subprocess_debugger(self.rpcclt)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000483 # reload remote debugger breakpoints for all PyShellEditWindows
484 debug.load_breakpoints()
Ned Deily86d669b2011-10-30 19:58:04 -0700485 self.compile.compiler.flags = self.original_compiler_flags
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000486 self.restarting = False
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000487 return self.rpcclt
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000488
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000489 def __request_interrupt(self):
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000490 self.rpcclt.remotecall("exec", "interrupt_the_server", (), {})
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000491
492 def interrupt_subprocess(self):
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000493 threading.Thread(target=self.__request_interrupt).start()
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000494
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000495 def kill_subprocess(self):
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000496 try:
497 self.rpcclt.close()
498 except AttributeError: # no socket
499 pass
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000500 self.unix_terminate()
501 self.tkconsole.executing = False
502 self.rpcclt = None
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000503
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000504 def unix_terminate(self):
505 "UNIX: make sure subprocess is terminated and collect status"
506 if hasattr(os, 'kill'):
507 try:
508 os.kill(self.rpcpid, SIGTERM)
509 except OSError:
510 # process already terminated:
511 return
512 else:
513 try:
514 os.waitpid(self.rpcpid, 0)
515 except OSError:
516 return
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000517
Terry Jan Reedyb98000a2012-01-31 02:09:25 -0500518 def transfer_path(self, with_cwd=False):
519 if with_cwd: # Issue 13506
520 path = [''] # include Current Working Directory
521 path.extend(sys.path)
522 else:
523 path = sys.path
Terry Jan Reedy1d4ae482012-01-31 02:55:32 -0500524
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000525 self.runcommand("""if 1:
526 import sys as _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +0000527 _sys.path = %r
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000528 del _sys
Terry Jan Reedyb98000a2012-01-31 02:09:25 -0500529 \n""" % (path,))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000530
Chui Tey5d2af632002-05-26 13:36:41 +0000531 active_seq = None
532
533 def poll_subprocess(self):
534 clt = self.rpcclt
535 if clt is None:
536 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000537 try:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000538 response = clt.pollresponse(self.active_seq, wait=0.05)
539 except (EOFError, IOError, KeyboardInterrupt):
540 # lost connection or subprocess terminated itself, restart
541 # [the KBI is from rpc.SocketIO.handle_EOF()]
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000542 if self.tkconsole.closing:
543 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000544 response = None
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000545 self.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000546 if response:
547 self.tkconsole.resetoutput()
548 self.active_seq = None
549 how, what = response
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000550 console = self.tkconsole.console
Chui Tey5d2af632002-05-26 13:36:41 +0000551 if how == "OK":
552 if what is not None:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000553 print >>console, repr(what)
Chui Tey5d2af632002-05-26 13:36:41 +0000554 elif how == "EXCEPTION":
Chui Tey5d2af632002-05-26 13:36:41 +0000555 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
556 self.remote_stack_viewer()
557 elif how == "ERROR":
Kurt B. Kaiser0930c432002-12-06 21:45:24 +0000558 errmsg = "PyShell.ModifiedInterpreter: Subprocess ERROR:\n"
559 print >>sys.__stderr__, errmsg, what
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000560 print >>console, errmsg, what
561 # we received a response to the currently active seq number:
Kurt B. Kaiserd112bc72006-08-16 05:01:42 +0000562 try:
563 self.tkconsole.endexecuting()
564 except AttributeError: # shell may have closed
565 pass
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000566 # Reschedule myself
567 if not self.tkconsole.closing:
568 self.tkconsole.text.after(self.tkconsole.pollinterval,
569 self.poll_subprocess)
Chui Tey5d2af632002-05-26 13:36:41 +0000570
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000571 debugger = None
572
573 def setdebugger(self, debugger):
574 self.debugger = debugger
575
576 def getdebugger(self):
577 return self.debugger
578
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000579 def open_remote_stack_viewer(self):
580 """Initiate the remote stack viewer from a separate thread.
581
582 This method is called from the subprocess, and by returning from this
583 method we allow the subprocess to unblock. After a bit the shell
584 requests the subprocess to open the remote stack viewer which returns a
Ezio Melottic569cfe2010-07-23 16:55:21 +0000585 static object looking at the last exception. It is queried through
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000586 the RPC mechanism.
587
588 """
589 self.tkconsole.text.after(300, self.remote_stack_viewer)
590 return
591
Chui Tey5d2af632002-05-26 13:36:41 +0000592 def remote_stack_viewer(self):
Florent Xiclunad630c042010-04-02 07:24:52 +0000593 from idlelib import RemoteObjectBrowser
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000594 oid = self.rpcclt.remotequeue("exec", "stackviewer", ("flist",), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000595 if oid is None:
596 self.tkconsole.root.bell()
597 return
598 item = RemoteObjectBrowser.StubObjectTreeItem(self.rpcclt, oid)
Florent Xiclunad630c042010-04-02 07:24:52 +0000599 from idlelib.TreeWidget import ScrolledCanvas, TreeNode
Chui Tey5d2af632002-05-26 13:36:41 +0000600 top = Toplevel(self.tkconsole.root)
Kurt B. Kaiser73360a32004-03-08 18:15:31 +0000601 theme = idleConf.GetOption('main','Theme','name')
602 background = idleConf.GetHighlight(theme, 'normal')['background']
603 sc = ScrolledCanvas(top, bg=background, highlightthickness=0)
Chui Tey5d2af632002-05-26 13:36:41 +0000604 sc.frame.pack(expand=1, fill="both")
605 node = TreeNode(sc.canvas, None, item)
606 node.expand()
607 # XXX Should GC the remote tree when closing the window
608
David Scherer7aced172000-08-15 01:13:23 +0000609 gid = 0
610
611 def execsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000612 "Like runsource() but assumes complete exec source"
David Scherer7aced172000-08-15 01:13:23 +0000613 filename = self.stuffsource(source)
614 self.execfile(filename, source)
615
616 def execfile(self, filename, source=None):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000617 "Execute an existing file"
David Scherer7aced172000-08-15 01:13:23 +0000618 if source is None:
619 source = open(filename, "r").read()
620 try:
621 code = compile(source, filename, "exec")
622 except (OverflowError, SyntaxError):
623 self.tkconsole.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000624 tkerr = self.tkconsole.stderr
625 print>>tkerr, '*** Error in script or command!\n'
626 print>>tkerr, 'Traceback (most recent call last):'
David Scherer7aced172000-08-15 01:13:23 +0000627 InteractiveInterpreter.showsyntaxerror(self, filename)
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000628 self.tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000629 else:
630 self.runcode(code)
631
632 def runsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000633 "Extend base class method: Stuff the source in the line cache first"
David Scherer7aced172000-08-15 01:13:23 +0000634 filename = self.stuffsource(source)
635 self.more = 0
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000636 self.save_warnings_filters = warnings.filters[:]
637 warnings.filterwarnings(action="error", category=SyntaxWarning)
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000638 if isinstance(source, types.UnicodeType):
Florent Xiclunad630c042010-04-02 07:24:52 +0000639 from idlelib import IOBinding
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000640 try:
641 source = source.encode(IOBinding.encoding)
642 except UnicodeError:
643 self.tkconsole.resetoutput()
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +0000644 self.write("Unsupported characters in input\n")
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000645 return
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000646 try:
Kurt B. Kaiser935ea9a2005-05-10 03:44:24 +0000647 # InteractiveInterpreter.runsource() calls its runcode() method,
648 # which is overridden (see below)
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000649 return InteractiveInterpreter.runsource(self, source, filename)
650 finally:
651 if self.save_warnings_filters is not None:
652 warnings.filters[:] = self.save_warnings_filters
653 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000654
655 def stuffsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000656 "Stuff source in the filename cache"
David Scherer7aced172000-08-15 01:13:23 +0000657 filename = "<pyshell#%d>" % self.gid
658 self.gid = self.gid + 1
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000659 lines = source.split("\n")
David Scherer7aced172000-08-15 01:13:23 +0000660 linecache.cache[filename] = len(source)+1, 0, lines, filename
661 return filename
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000662
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000663 def prepend_syspath(self, filename):
664 "Prepend sys.path with file's directory if not already included"
665 self.runcommand("""if 1:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000666 _filename = %r
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000667 import sys as _sys
668 from os.path import dirname as _dirname
669 _dir = _dirname(_filename)
670 if not _dir in _sys.path:
671 _sys.path.insert(0, _dir)
672 del _filename, _sys, _dirname, _dir
Walter Dörwald70a6b492004-02-12 17:35:32 +0000673 \n""" % (filename,))
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000674
David Scherer7aced172000-08-15 01:13:23 +0000675 def showsyntaxerror(self, filename=None):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000676 """Extend base class method: Add Colorizing
677
678 Color the offending position instead of printing it and pointing at it
679 with a caret.
680
681 """
David Scherer7aced172000-08-15 01:13:23 +0000682 text = self.tkconsole.text
683 stuff = self.unpackerror()
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000684 if stuff:
685 msg, lineno, offset, line = stuff
686 if lineno == 1:
687 pos = "iomark + %d chars" % (offset-1)
688 else:
689 pos = "iomark linestart + %d lines + %d chars" % \
690 (lineno-1, offset-1)
691 text.tag_add("ERROR", pos)
692 text.see(pos)
693 char = text.get(pos)
694 if char and char in IDENTCHARS:
695 text.tag_add("ERROR", pos + " wordstart", pos)
696 self.tkconsole.resetoutput()
697 self.write("SyntaxError: %s\n" % str(msg))
698 else:
David Scherer7aced172000-08-15 01:13:23 +0000699 self.tkconsole.resetoutput()
700 InteractiveInterpreter.showsyntaxerror(self, filename)
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000701 self.tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000702
703 def unpackerror(self):
704 type, value, tb = sys.exc_info()
705 ok = type is SyntaxError
706 if ok:
707 try:
708 msg, (dummy_filename, lineno, offset, line) = value
Kurt B. Kaiserbea57c62003-07-09 04:27:24 +0000709 if not offset:
710 offset = 0
David Scherer7aced172000-08-15 01:13:23 +0000711 except:
712 ok = 0
713 if ok:
714 return msg, lineno, offset, line
715 else:
716 return None
717
718 def showtraceback(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000719 "Extend base class method to reset output properly"
David Scherer7aced172000-08-15 01:13:23 +0000720 self.tkconsole.resetoutput()
721 self.checklinecache()
722 InteractiveInterpreter.showtraceback(self)
Chui Tey5d2af632002-05-26 13:36:41 +0000723 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
724 self.tkconsole.open_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +0000725
726 def checklinecache(self):
727 c = linecache.cache
728 for key in c.keys():
729 if key[:1] + key[-1:] != "<>":
730 del c[key]
731
Chui Tey5d2af632002-05-26 13:36:41 +0000732 def runcommand(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000733 "Run the code without invoking the debugger"
Chui Tey5d2af632002-05-26 13:36:41 +0000734 # The code better not raise an exception!
735 if self.tkconsole.executing:
Neal Norwitzf4c4f112002-11-30 18:49:10 +0000736 self.display_executing_dialog()
Chui Tey5d2af632002-05-26 13:36:41 +0000737 return 0
738 if self.rpcclt:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000739 self.rpcclt.remotequeue("exec", "runcode", (code,), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000740 else:
741 exec code in self.locals
742 return 1
743
David Scherer7aced172000-08-15 01:13:23 +0000744 def runcode(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000745 "Override base class method"
Chui Tey5d2af632002-05-26 13:36:41 +0000746 if self.tkconsole.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000747 self.interp.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000748 self.checklinecache()
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000749 if self.save_warnings_filters is not None:
750 warnings.filters[:] = self.save_warnings_filters
751 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000752 debugger = self.debugger
753 try:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000754 self.tkconsole.beginexecuting()
Kurt B. Kaiserdddeb0e2007-02-06 03:21:40 +0000755 if not debugger and self.rpcclt is not None:
756 self.active_seq = self.rpcclt.asyncqueue("exec", "runcode",
757 (code,), {})
758 elif debugger:
759 debugger.run(code, self.locals)
760 else:
761 exec code in self.locals
762 except SystemExit:
763 if not self.tkconsole.closing:
764 if tkMessageBox.askyesno(
765 "Exit?",
766 "Do you want to exit altogether?",
767 default="yes",
768 master=self.tkconsole.text):
Kurt B. Kaiserf137e1d2006-08-16 07:04:17 +0000769 raise
Kurt B. Kaiserdddeb0e2007-02-06 03:21:40 +0000770 else:
771 self.showtraceback()
772 else:
773 raise
774 except:
775 if use_subprocess:
776 print >>self.tkconsole.stderr, \
777 "IDLE internal error in runcode()"
David Scherer7aced172000-08-15 01:13:23 +0000778 self.showtraceback()
Kurt B. Kaiserdddeb0e2007-02-06 03:21:40 +0000779 self.tkconsole.endexecuting()
780 else:
781 if self.tkconsole.canceled:
782 self.tkconsole.canceled = False
783 print >>self.tkconsole.stderr, "KeyboardInterrupt"
784 else:
785 self.showtraceback()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000786 finally:
787 if not use_subprocess:
Kurt B. Kaiserd112bc72006-08-16 05:01:42 +0000788 try:
789 self.tkconsole.endexecuting()
790 except AttributeError: # shell may have closed
791 pass
David Scherer7aced172000-08-15 01:13:23 +0000792
793 def write(self, s):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000794 "Override base class method"
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000795 self.tkconsole.stderr.write(s)
David Scherer7aced172000-08-15 01:13:23 +0000796
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000797 def display_port_binding_error(self):
798 tkMessageBox.showerror(
799 "Port Binding Error",
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +0000800 "IDLE can't bind to a TCP/IP port, which is necessary to "
801 "communicate with its Python execution server. This might be "
802 "because no networking is installed on this computer. "
803 "Run IDLE with the -n command line switch to start without a "
804 "subprocess and refer to Help/IDLE Help 'Running without a "
805 "subprocess' for further details.",
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000806 master=self.tkconsole.text)
807
808 def display_no_subprocess_error(self):
809 tkMessageBox.showerror(
810 "Subprocess Startup Error",
811 "IDLE's subprocess didn't make connection. Either IDLE can't "
812 "start a subprocess or personal firewall software is blocking "
813 "the connection.",
814 master=self.tkconsole.text)
815
816 def display_executing_dialog(self):
817 tkMessageBox.showerror(
818 "Already executing",
819 "The Python Shell window is already executing a command; "
820 "please wait until it is finished.",
821 master=self.tkconsole.text)
822
823
David Scherer7aced172000-08-15 01:13:23 +0000824class PyShell(OutputWindow):
825
826 shell_title = "Python Shell"
827
828 # Override classes
829 ColorDelegator = ModifiedColorDelegator
830 UndoDelegator = ModifiedUndoDelegator
831
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000832 # Override menus
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000833 menu_specs = [
834 ("file", "_File"),
835 ("edit", "_Edit"),
Kurt B. Kaiser4cc5ef52003-01-22 00:23:23 +0000836 ("debug", "_Debug"),
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000837 ("options", "_Options"),
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000838 ("windows", "_Windows"),
839 ("help", "_Help"),
840 ]
David Scherer7aced172000-08-15 01:13:23 +0000841
Ronald Oussoren19302d92006-06-11 14:33:36 +0000842 if macosxSupport.runningAsOSXApp():
843 del menu_specs[-3]
844 menu_specs[-2] = ("windows", "_Window")
845
846
David Scherer7aced172000-08-15 01:13:23 +0000847 # New classes
Florent Xiclunad630c042010-04-02 07:24:52 +0000848 from idlelib.IdleHistory import History
David Scherer7aced172000-08-15 01:13:23 +0000849
850 def __init__(self, flist=None):
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000851 if use_subprocess:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000852 ms = self.menu_specs
853 if ms[2][0] != "shell":
Kurt B. Kaiser7ae35482006-08-16 21:45:59 +0000854 ms.insert(2, ("shell", "She_ll"))
David Scherer7aced172000-08-15 01:13:23 +0000855 self.interp = ModifiedInterpreter(self)
856 if flist is None:
857 root = Tk()
858 fixwordbreaks(root)
859 root.withdraw()
860 flist = PyShellFileList(root)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000861 #
David Scherer7aced172000-08-15 01:13:23 +0000862 OutputWindow.__init__(self, flist, None, None)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000863 #
Kurt B. Kaiser6af44982005-01-19 00:22:59 +0000864## self.config(usetabs=1, indentwidth=8, context_use_ps1=1)
865 self.usetabs = True
866 # indentwidth must be 8 when using tabs. See note in EditorWindow:
867 self.indentwidth = 8
868 self.context_use_ps1 = True
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000869 #
David Scherer7aced172000-08-15 01:13:23 +0000870 text = self.text
871 text.configure(wrap="char")
872 text.bind("<<newline-and-indent>>", self.enter_callback)
873 text.bind("<<plain-newline-and-indent>>", self.linefeed_callback)
874 text.bind("<<interrupt-execution>>", self.cancel_callback)
David Scherer7aced172000-08-15 01:13:23 +0000875 text.bind("<<end-of-file>>", self.eof_callback)
876 text.bind("<<open-stack-viewer>>", self.open_stack_viewer)
Kurt B. Kaiser57bfe5d2003-05-10 00:09:52 +0000877 text.bind("<<toggle-debugger>>", self.toggle_debugger)
David Scherer7aced172000-08-15 01:13:23 +0000878 text.bind("<<toggle-jit-stack-viewer>>", self.toggle_jit_stack_viewer)
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000879 if use_subprocess:
880 text.bind("<<view-restart>>", self.view_restart_mark)
881 text.bind("<<restart-shell>>", self.restart_shell)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000882 #
David Scherer7aced172000-08-15 01:13:23 +0000883 self.save_stdout = sys.stdout
884 self.save_stderr = sys.stderr
885 self.save_stdin = sys.stdin
Florent Xiclunad630c042010-04-02 07:24:52 +0000886 from idlelib import IOBinding
Martin v. Löwise2b56242012-07-25 10:56:22 +0200887 self.stdin = PseudoInputFile(self)
Martin v. Löwisbcc651a2003-06-22 07:52:56 +0000888 self.stdout = PseudoFile(self, "stdout", IOBinding.encoding)
889 self.stderr = PseudoFile(self, "stderr", IOBinding.encoding)
890 self.console = PseudoFile(self, "console", IOBinding.encoding)
Chui Tey5d2af632002-05-26 13:36:41 +0000891 if not use_subprocess:
892 sys.stdout = self.stdout
893 sys.stderr = self.stderr
Martin v. Löwise2b56242012-07-25 10:56:22 +0200894 sys.stdin = self.stdin
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000895 #
David Scherer7aced172000-08-15 01:13:23 +0000896 self.history = self.History(self.text)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000897 #
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000898 self.pollinterval = 50 # millisec
Chui Tey5d2af632002-05-26 13:36:41 +0000899
Kurt B. Kaiser4d5bc602004-06-06 01:29:22 +0000900 def get_standard_extension_names(self):
901 return idleConf.GetExtensions(shell_only=True)
902
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000903 reading = False
904 executing = False
905 canceled = False
906 endoffile = False
907 closing = False
David Scherer7aced172000-08-15 01:13:23 +0000908
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +0000909 def set_warning_stream(self, stream):
Skip Montanarod9161422004-07-06 21:53:27 +0000910 global warning_stream
911 warning_stream = stream
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +0000912
913 def get_warning_stream(self):
914 return warning_stream
915
David Scherer7aced172000-08-15 01:13:23 +0000916 def toggle_debugger(self, event=None):
917 if self.executing:
918 tkMessageBox.showerror("Don't debug now",
919 "You can only toggle the debugger when idle",
920 master=self.text)
921 self.set_debugger_indicator()
922 return "break"
923 else:
924 db = self.interp.getdebugger()
925 if db:
926 self.close_debugger()
927 else:
928 self.open_debugger()
929
930 def set_debugger_indicator(self):
931 db = self.interp.getdebugger()
932 self.setvar("<<toggle-debugger>>", not not db)
933
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000934 def toggle_jit_stack_viewer(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +0000935 pass # All we need is the variable
936
937 def close_debugger(self):
938 db = self.interp.getdebugger()
939 if db:
940 self.interp.setdebugger(None)
941 db.close()
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000942 if self.interp.rpcclt:
943 RemoteDebugger.close_remote_debugger(self.interp.rpcclt)
David Scherer7aced172000-08-15 01:13:23 +0000944 self.resetoutput()
945 self.console.write("[DEBUG OFF]\n")
946 sys.ps1 = ">>> "
947 self.showprompt()
948 self.set_debugger_indicator()
949
950 def open_debugger(self):
Chui Tey5d2af632002-05-26 13:36:41 +0000951 if self.interp.rpcclt:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000952 dbg_gui = RemoteDebugger.start_remote_debugger(self.interp.rpcclt,
953 self)
954 else:
955 dbg_gui = Debugger.Debugger(self)
956 self.interp.setdebugger(dbg_gui)
957 dbg_gui.load_breakpoints()
Chui Tey5d2af632002-05-26 13:36:41 +0000958 sys.ps1 = "[DEBUG ON]\n>>> "
959 self.showprompt()
960 self.set_debugger_indicator()
961
David Scherer7aced172000-08-15 01:13:23 +0000962 def beginexecuting(self):
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000963 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +0000964 self.resetoutput()
965 self.executing = 1
David Scherer7aced172000-08-15 01:13:23 +0000966
967 def endexecuting(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000968 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +0000969 self.executing = 0
970 self.canceled = 0
Chui Tey5d2af632002-05-26 13:36:41 +0000971 self.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000972
973 def close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000974 "Extend EditorWindow.close()"
David Scherer7aced172000-08-15 01:13:23 +0000975 if self.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000976 response = tkMessageBox.askokcancel(
David Scherer7aced172000-08-15 01:13:23 +0000977 "Kill?",
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000978 "The program is still running!\n Do you want to kill it?",
David Scherer7aced172000-08-15 01:13:23 +0000979 default="ok",
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000980 parent=self.text)
Benjamin Peterson5b63acd2008-03-29 15:24:25 +0000981 if response is False:
David Scherer7aced172000-08-15 01:13:23 +0000982 return "cancel"
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +0000983 if self.reading:
984 self.top.quit()
985 self.canceled = True
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000986 self.closing = True
987 # Wait for poll_subprocess() rescheduling to stop
988 self.text.after(2 * self.pollinterval, self.close2)
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000989
990 def close2(self):
991 return EditorWindow.close(self)
David Scherer7aced172000-08-15 01:13:23 +0000992
993 def _close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000994 "Extend EditorWindow._close(), shut down debugger and execution server"
David Scherer7aced172000-08-15 01:13:23 +0000995 self.close_debugger()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000996 if use_subprocess:
997 self.interp.kill_subprocess()
David Scherer7aced172000-08-15 01:13:23 +0000998 # Restore std streams
999 sys.stdout = self.save_stdout
1000 sys.stderr = self.save_stderr
1001 sys.stdin = self.save_stdin
1002 # Break cycles
1003 self.interp = None
1004 self.console = None
David Scherer7aced172000-08-15 01:13:23 +00001005 self.flist.pyshell = None
1006 self.history = None
Kurt B. Kaiser83118c62002-06-24 17:03:37 +00001007 EditorWindow._close(self)
David Scherer7aced172000-08-15 01:13:23 +00001008
1009 def ispythonsource(self, filename):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +00001010 "Override EditorWindow method: never remove the colorizer"
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001011 return True
David Scherer7aced172000-08-15 01:13:23 +00001012
1013 def short_title(self):
1014 return self.shell_title
1015
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +00001016 COPYRIGHT = \
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001017 'Type "copyright", "credits" or "license()" for more information.'
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +00001018
David Scherer7aced172000-08-15 01:13:23 +00001019 def begin(self):
1020 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001021 if use_subprocess:
1022 nosub = ''
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001023 client = self.interp.start_subprocess()
1024 if not client:
1025 self.close()
Kurt B. Kaiser76637292004-01-21 22:10:01 +00001026 return False
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001027 else:
1028 nosub = "==== No Subprocess ===="
Raymond Hettingerbf3f69e2009-01-26 23:29:09 +00001029 self.write("Python %s on %s\n%s\n%s" %
1030 (sys.version, sys.platform, self.COPYRIGHT, nosub))
David Scherer7aced172000-08-15 01:13:23 +00001031 self.showprompt()
Georg Brandl6634bf22008-05-20 07:13:37 +00001032 import Tkinter
1033 Tkinter._default_root = None # 03Jan04 KBK What's this?
Kurt B. Kaiser76637292004-01-21 22:10:01 +00001034 return True
David Scherer7aced172000-08-15 01:13:23 +00001035
1036 def readline(self):
1037 save = self.reading
1038 try:
1039 self.reading = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001040 self.top.mainloop() # nested mainloop()
David Scherer7aced172000-08-15 01:13:23 +00001041 finally:
1042 self.reading = save
1043 line = self.text.get("iomark", "end-1c")
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001044 if len(line) == 0: # may be EOF if we quit our mainloop with Ctrl-C
1045 line = "\n"
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001046 if isinstance(line, unicode):
Florent Xiclunad630c042010-04-02 07:24:52 +00001047 from idlelib import IOBinding
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001048 try:
1049 line = line.encode(IOBinding.encoding)
1050 except UnicodeError:
1051 pass
David Scherer7aced172000-08-15 01:13:23 +00001052 self.resetoutput()
1053 if self.canceled:
1054 self.canceled = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001055 if not use_subprocess:
1056 raise KeyboardInterrupt
David Scherer7aced172000-08-15 01:13:23 +00001057 if self.endoffile:
1058 self.endoffile = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001059 line = ""
David Scherer7aced172000-08-15 01:13:23 +00001060 return line
1061
1062 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001063 return True
David Scherer7aced172000-08-15 01:13:23 +00001064
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001065 def cancel_callback(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +00001066 try:
1067 if self.text.compare("sel.first", "!=", "sel.last"):
1068 return # Active selection -- always use default binding
1069 except:
1070 pass
1071 if not (self.executing or self.reading):
1072 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001073 self.interp.write("KeyboardInterrupt\n")
David Scherer7aced172000-08-15 01:13:23 +00001074 self.showprompt()
1075 return "break"
1076 self.endoffile = 0
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001077 self.canceled = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001078 if (self.executing and self.interp.rpcclt):
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +00001079 if self.interp.getdebugger():
1080 self.interp.restart_subprocess()
1081 else:
1082 self.interp.interrupt_subprocess()
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001083 if self.reading:
1084 self.top.quit() # exit the nested mainloop() in readline()
David Scherer7aced172000-08-15 01:13:23 +00001085 return "break"
1086
1087 def eof_callback(self, event):
1088 if self.executing and not self.reading:
1089 return # Let the default binding (delete next char) take over
1090 if not (self.text.compare("iomark", "==", "insert") and
1091 self.text.compare("insert", "==", "end-1c")):
1092 return # Let the default binding (delete next char) take over
1093 if not self.executing:
David Scherer7aced172000-08-15 01:13:23 +00001094 self.resetoutput()
1095 self.close()
1096 else:
1097 self.canceled = 0
1098 self.endoffile = 1
1099 self.top.quit()
1100 return "break"
1101
David Scherer7aced172000-08-15 01:13:23 +00001102 def linefeed_callback(self, event):
1103 # Insert a linefeed without entering anything (still autoindented)
1104 if self.reading:
1105 self.text.insert("insert", "\n")
1106 self.text.see("insert")
1107 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001108 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001109 return "break"
1110
1111 def enter_callback(self, event):
1112 if self.executing and not self.reading:
1113 return # Let the default binding (insert '\n') take over
1114 # If some text is selected, recall the selection
1115 # (but only if this before the I/O mark)
1116 try:
1117 sel = self.text.get("sel.first", "sel.last")
1118 if sel:
1119 if self.text.compare("sel.last", "<=", "iomark"):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001120 self.recall(sel, event)
David Scherer7aced172000-08-15 01:13:23 +00001121 return "break"
1122 except:
1123 pass
1124 # If we're strictly before the line containing iomark, recall
1125 # the current line, less a leading prompt, less leading or
1126 # trailing whitespace
1127 if self.text.compare("insert", "<", "iomark linestart"):
1128 # Check if there's a relevant stdin range -- if so, use it
1129 prev = self.text.tag_prevrange("stdin", "insert")
1130 if prev and self.text.compare("insert", "<", prev[1]):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001131 self.recall(self.text.get(prev[0], prev[1]), event)
David Scherer7aced172000-08-15 01:13:23 +00001132 return "break"
1133 next = self.text.tag_nextrange("stdin", "insert")
1134 if next and self.text.compare("insert lineend", ">=", next[0]):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001135 self.recall(self.text.get(next[0], next[1]), event)
David Scherer7aced172000-08-15 01:13:23 +00001136 return "break"
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001137 # No stdin mark -- just get the current line, less any prompt
Kurt B. Kaiserb1754452005-11-18 22:05:48 +00001138 indices = self.text.tag_nextrange("console", "insert linestart")
1139 if indices and \
1140 self.text.compare(indices[0], "<=", "insert linestart"):
1141 self.recall(self.text.get(indices[1], "insert lineend"), event)
1142 else:
1143 self.recall(self.text.get("insert linestart", "insert lineend"), event)
David Scherer7aced172000-08-15 01:13:23 +00001144 return "break"
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001145 # If we're between the beginning of the line and the iomark, i.e.
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001146 # in the prompt area, move to the end of the prompt
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001147 if self.text.compare("insert", "<", "iomark"):
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001148 self.text.mark_set("insert", "iomark")
David Scherer7aced172000-08-15 01:13:23 +00001149 # If we're in the current input and there's only whitespace
1150 # beyond the cursor, erase that whitespace first
1151 s = self.text.get("insert", "end-1c")
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001152 if s and not s.strip():
David Scherer7aced172000-08-15 01:13:23 +00001153 self.text.delete("insert", "end-1c")
1154 # If we're in the current input before its last line,
1155 # insert a newline right at the insert point
1156 if self.text.compare("insert", "<", "end-1c linestart"):
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001157 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001158 return "break"
1159 # We're in the last line; append a newline and submit it
1160 self.text.mark_set("insert", "end-1c")
1161 if self.reading:
1162 self.text.insert("insert", "\n")
1163 self.text.see("insert")
1164 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001165 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001166 self.text.tag_add("stdin", "iomark", "end-1c")
1167 self.text.update_idletasks()
1168 if self.reading:
1169 self.top.quit() # Break out of recursive mainloop() in raw_input()
1170 else:
1171 self.runit()
1172 return "break"
1173
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001174 def recall(self, s, event):
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001175 # remove leading and trailing empty or whitespace lines
1176 s = re.sub(r'^\s*\n', '' , s)
1177 s = re.sub(r'\n\s*$', '', s)
1178 lines = s.split('\n')
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001179 self.text.undo_block_start()
1180 try:
1181 self.text.tag_remove("sel", "1.0", "end")
1182 self.text.mark_set("insert", "end-1c")
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001183 prefix = self.text.get("insert linestart", "insert")
1184 if prefix.rstrip().endswith(':'):
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001185 self.newline_and_indent_event(event)
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001186 prefix = self.text.get("insert linestart", "insert")
1187 self.text.insert("insert", lines[0].strip())
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001188 if len(lines) > 1:
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001189 orig_base_indent = re.search(r'^([ \t]*)', lines[0]).group(0)
1190 new_base_indent = re.search(r'^([ \t]*)', prefix).group(0)
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001191 for line in lines[1:]:
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001192 if line.startswith(orig_base_indent):
1193 # replace orig base indentation with new indentation
1194 line = new_base_indent + line[len(orig_base_indent):]
1195 self.text.insert('insert', '\n'+line.rstrip())
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001196 finally:
1197 self.text.see("insert")
1198 self.text.undo_block_stop()
David Scherer7aced172000-08-15 01:13:23 +00001199
1200 def runit(self):
1201 line = self.text.get("iomark", "end-1c")
1202 # Strip off last newline and surrounding whitespace.
1203 # (To allow you to hit return twice to end a statement.)
1204 i = len(line)
1205 while i > 0 and line[i-1] in " \t":
1206 i = i-1
1207 if i > 0 and line[i-1] == "\n":
1208 i = i-1
1209 while i > 0 and line[i-1] in " \t":
1210 i = i-1
1211 line = line[:i]
1212 more = self.interp.runsource(line)
David Scherer7aced172000-08-15 01:13:23 +00001213
David Scherer7aced172000-08-15 01:13:23 +00001214 def open_stack_viewer(self, event=None):
Chui Tey5d2af632002-05-26 13:36:41 +00001215 if self.interp.rpcclt:
1216 return self.interp.remote_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +00001217 try:
1218 sys.last_traceback
1219 except:
1220 tkMessageBox.showerror("No stack trace",
1221 "There is no stack trace yet.\n"
1222 "(sys.last_traceback is not defined)",
1223 master=self.text)
1224 return
Florent Xiclunad630c042010-04-02 07:24:52 +00001225 from idlelib.StackViewer import StackBrowser
David Scherer7aced172000-08-15 01:13:23 +00001226 sv = StackBrowser(self.root, self.flist)
1227
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001228 def view_restart_mark(self, event=None):
1229 self.text.see("iomark")
1230 self.text.see("restart")
1231
1232 def restart_shell(self, event=None):
Terry Jan Reedyb98000a2012-01-31 02:09:25 -05001233 "Callback for Run/Restart Shell Cntl-F6"
1234 self.interp.restart_subprocess(with_cwd=True)
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001235
David Scherer7aced172000-08-15 01:13:23 +00001236 def showprompt(self):
1237 self.resetoutput()
1238 try:
1239 s = str(sys.ps1)
1240 except:
1241 s = ""
1242 self.console.write(s)
1243 self.text.mark_set("insert", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001244 self.set_line_and_column()
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +00001245 self.io.reset_undo()
David Scherer7aced172000-08-15 01:13:23 +00001246
1247 def resetoutput(self):
1248 source = self.text.get("iomark", "end-1c")
1249 if self.history:
1250 self.history.history_store(source)
1251 if self.text.get("end-2c") != "\n":
1252 self.text.insert("end-1c", "\n")
1253 self.text.mark_set("iomark", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001254 self.set_line_and_column()
David Scherer7aced172000-08-15 01:13:23 +00001255 sys.stdout.softspace = 0
1256
1257 def write(self, s, tags=()):
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001258 try:
1259 self.text.mark_gravity("iomark", "right")
1260 OutputWindow.write(self, s, tags, "iomark")
1261 self.text.mark_gravity("iomark", "left")
1262 except:
1263 pass
David Scherer7aced172000-08-15 01:13:23 +00001264 if self.canceled:
1265 self.canceled = 0
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001266 if not use_subprocess:
1267 raise KeyboardInterrupt
David Scherer7aced172000-08-15 01:13:23 +00001268
Andrew Svetlov5018db72012-11-01 22:39:14 +02001269 def rmenu_check_cut(self):
1270 try:
1271 if self.text.compare('sel.first', '<', 'iomark'):
1272 return 'disabled'
1273 except TclError: # no selection, so the index 'sel.first' doesn't exist
1274 return 'disabled'
1275 return super(PyShell, self).rmenu_check_cut()
1276
1277 def rmenu_check_paste(self):
1278 if self.text.compare('insert', '<', 'iomark'):
1279 return 'disabled'
1280 return super(PyShell, self).rmenu_check_paste()
1281
Kurt B. Kaiserdcba6622004-12-21 22:10:32 +00001282class PseudoFile(object):
David Scherer7aced172000-08-15 01:13:23 +00001283
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001284 def __init__(self, shell, tags, encoding=None):
David Scherer7aced172000-08-15 01:13:23 +00001285 self.shell = shell
1286 self.tags = tags
Chui Tey5d2af632002-05-26 13:36:41 +00001287 self.softspace = 0
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001288 self.encoding = encoding
David Scherer7aced172000-08-15 01:13:23 +00001289
1290 def write(self, s):
Terry Jan Reedyf8fc6742012-07-09 17:57:13 -04001291 if not isinstance(s, (basestring, bytearray)):
1292 raise TypeError('must be string, not ' + type(s).__name__)
David Scherer7aced172000-08-15 01:13:23 +00001293 self.shell.write(s, self.tags)
1294
Florent Xiclunad630c042010-04-02 07:24:52 +00001295 def writelines(self, lines):
1296 for line in lines:
1297 self.write(line)
David Scherer7aced172000-08-15 01:13:23 +00001298
1299 def flush(self):
1300 pass
1301
1302 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001303 return True
David Scherer7aced172000-08-15 01:13:23 +00001304
Martin v. Löwise2b56242012-07-25 10:56:22 +02001305class PseudoInputFile(object):
1306 def __init__(self, shell):
1307 self.readline = shell.readline
1308 self.isatty = shell.isatty
1309
1310 def write(self, s):
1311 raise io.UnsupportedOperation("not writable")
1312 writelines = write
1313
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001314
David Scherer7aced172000-08-15 01:13:23 +00001315usage_msg = """\
David Scherer7aced172000-08-15 01:13:23 +00001316
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001317USAGE: idle [-deins] [-t title] [file]*
1318 idle [-dns] [-t title] (-c cmd | -r file) [arg]*
1319 idle [-dns] [-t title] - [arg]*
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001320
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001321 -h print this help message and exit
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001322 -n run IDLE without a subprocess (see Help/IDLE Help for details)
David Scherer7aced172000-08-15 01:13:23 +00001323
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001324The following options will override the IDLE 'settings' configuration:
Kurt B. Kaiser96d88422001-07-17 04:59:01 +00001325
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001326 -e open an edit window
1327 -i open a shell window
1328
1329The following options imply -i and will open a shell:
1330
1331 -c cmd run the command in a shell, or
1332 -r file run script from file
1333
1334 -d enable the debugger
1335 -s run $IDLESTARTUP or $PYTHONSTARTUP before anything else
1336 -t title set title of shell window
1337
1338A default edit window will be bypassed when -c, -r, or - are used.
1339
1340[arg]* are passed to the command (-c) or script (-r) in sys.argv[1:].
1341
1342Examples:
1343
1344idle
1345 Open an edit window or shell depending on IDLE's configuration.
1346
1347idle foo.py foobar.py
1348 Edit the files, also open a shell if configured to start with shell.
1349
1350idle -est "Baz" foo.py
1351 Run $IDLESTARTUP or $PYTHONSTARTUP, edit foo.py, and open a shell
1352 window with the title "Baz".
1353
1354idle -c "import sys; print sys.argv" "foo"
1355 Open a shell window and run the command, passing "-c" in sys.argv[0]
1356 and "foo" in sys.argv[1].
1357
1358idle -d -s -r foo.py "Hello World"
1359 Open a shell window, run a startup script, enable the debugger, and
1360 run foo.py, passing "foo.py" in sys.argv[0] and "Hello World" in
1361 sys.argv[1].
1362
1363echo "import sys; print sys.argv" | idle - "foobar"
1364 Open a shell window, run the script piped in, passing '' in sys.argv[0]
1365 and "foobar" in sys.argv[1].
David Scherer7aced172000-08-15 01:13:23 +00001366"""
1367
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001368def main():
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001369 global flist, root, use_subprocess
David Scherer7aced172000-08-15 01:13:23 +00001370
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001371 use_subprocess = True
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +00001372 enable_shell = True
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001373 enable_edit = False
1374 debug = False
1375 cmd = None
1376 script = None
1377 startup = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001378 try:
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001379 opts, args = getopt.getopt(sys.argv[1:], "c:deihnr:st:")
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001380 except getopt.error, msg:
1381 sys.stderr.write("Error: %s\n" % str(msg))
1382 sys.stderr.write(usage_msg)
1383 sys.exit(2)
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001384 for o, a in opts:
1385 if o == '-c':
1386 cmd = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001387 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001388 if o == '-d':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001389 debug = True
1390 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001391 if o == '-e':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001392 enable_edit = True
Kurt B. Kaiser013d6cc2009-04-04 07:03:48 +00001393 enable_shell = False
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001394 if o == '-h':
1395 sys.stdout.write(usage_msg)
1396 sys.exit()
1397 if o == '-i':
1398 enable_shell = True
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001399 if o == '-n':
1400 use_subprocess = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001401 if o == '-r':
1402 script = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001403 if os.path.isfile(script):
1404 pass
1405 else:
1406 print "No script file: ", script
1407 sys.exit()
1408 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001409 if o == '-s':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001410 startup = True
1411 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001412 if o == '-t':
1413 PyShell.shell_title = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001414 enable_shell = True
1415 if args and args[0] == '-':
1416 cmd = sys.stdin.read()
1417 enable_shell = True
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001418 # process sys.argv and sys.path:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001419 for i in range(len(sys.path)):
1420 sys.path[i] = os.path.abspath(sys.path[i])
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001421 if args and args[0] == '-':
1422 sys.argv = [''] + args[1:]
1423 elif cmd:
1424 sys.argv = ['-c'] + args
1425 elif script:
1426 sys.argv = [script] + args
1427 elif args:
1428 enable_edit = True
1429 pathx = []
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001430 for filename in args:
1431 pathx.append(os.path.dirname(filename))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001432 for dir in pathx:
1433 dir = os.path.abspath(dir)
Florent Xiclunad630c042010-04-02 07:24:52 +00001434 if dir not in sys.path:
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001435 sys.path.insert(0, dir)
Kurt B. Kaiserff002b92002-12-21 21:39:11 +00001436 else:
1437 dir = os.getcwd()
1438 if not dir in sys.path:
1439 sys.path.insert(0, dir)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001440 # check the IDLE settings configuration (but command line overrides)
1441 edit_start = idleConf.GetOption('main', 'General',
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001442 'editor-on-startup', type='bool')
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001443 enable_edit = enable_edit or edit_start
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001444 # start editor and/or shell windows:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001445 root = Tk(className="Idle")
Ronald Oussoren19302d92006-06-11 14:33:36 +00001446
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001447 fixwordbreaks(root)
1448 root.withdraw()
1449 flist = PyShellFileList(root)
Ronald Oussoren19302d92006-06-11 14:33:36 +00001450 macosxSupport.setupApp(root, flist)
1451
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001452 if enable_edit:
1453 if not (cmd or script):
Andrew Svetlov7c010ee2012-03-21 13:35:08 +02001454 for filename in args[:]:
1455 if flist.open(filename) is None:
1456 # filename is a directory actually, disconsider it
1457 args.remove(filename)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001458 if not args:
1459 flist.new()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001460 if enable_shell:
Ronald Oussoren19302d92006-06-11 14:33:36 +00001461 shell = flist.open_shell()
1462 if not shell:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001463 return # couldn't open shell
Ronald Oussoren19302d92006-06-11 14:33:36 +00001464
1465 if macosxSupport.runningAsOSXApp() and flist.dict:
1466 # On OSX: when the user has double-clicked on a file that causes
Tim Peters4f96f1f2006-06-11 19:42:51 +00001467 # IDLE to be launched the shell window will open just in front of
1468 # the file she wants to see. Lower the interpreter window when
Ronald Oussoren19302d92006-06-11 14:33:36 +00001469 # there are open files.
1470 shell.top.lower()
1471
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001472 shell = flist.pyshell
1473 # handle remaining options:
1474 if debug:
1475 shell.open_debugger()
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001476 if startup:
1477 filename = os.environ.get("IDLESTARTUP") or \
1478 os.environ.get("PYTHONSTARTUP")
1479 if filename and os.path.isfile(filename):
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001480 shell.interp.execfile(filename)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001481 if shell and cmd or script:
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001482 shell.interp.runcommand("""if 1:
1483 import sys as _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001484 _sys.argv = %r
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001485 del _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001486 \n""" % (sys.argv,))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001487 if cmd:
1488 shell.interp.execsource(cmd)
1489 elif script:
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001490 shell.interp.prepend_syspath(script)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001491 shell.interp.execfile(script)
Ronald Oussoren19302d92006-06-11 14:33:36 +00001492
Ned Deily2a6f4b32011-01-30 00:18:47 +00001493 # Check for problematic OS X Tk versions and print a warning message
1494 # in the IDLE shell window; this is less intrusive than always opening
1495 # a separate window.
1496 tkversionwarning = macosxSupport.tkVersionWarning(root)
1497 if tkversionwarning:
1498 shell.interp.runcommand(''.join(("print('", tkversionwarning, "')")))
1499
Terry Jan Reedyeaa7e782012-05-26 20:33:32 -04001500 while flist.inversedict: # keep IDLE running while files are open.
1501 root.mainloop()
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001502 root.destroy()
1503
David Scherer7aced172000-08-15 01:13:23 +00001504if __name__ == "__main__":
Kurt B. Kaiser9e8b8282003-06-15 17:38:45 +00001505 sys.modules['PyShell'] = sys.modules['__main__']
David Scherer7aced172000-08-15 01:13:23 +00001506 main()