blob: 6524dffa127dae8596cfb5bfe7a83bdee9d7b793 [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
David Scherer7aced172000-08-15 01:13:23 +000014
15import linecache
16from code import InteractiveInterpreter
17
Kurt B. Kaiser2303b1c2003-11-24 05:26:16 +000018try:
Georg Brandl6634bf22008-05-20 07:13:37 +000019 from Tkinter import *
Kurt B. Kaiser2303b1c2003-11-24 05:26:16 +000020except ImportError:
Georg Brandl6634bf22008-05-20 07:13:37 +000021 print>>sys.__stderr__, "** IDLE can't import Tkinter. " \
Kurt B. Kaiser2303b1c2003-11-24 05:26:16 +000022 "Your Python may not be configured for Tk. **"
23 sys.exit(1)
Georg Brandl6634bf22008-05-20 07:13:37 +000024import tkMessageBox
David Scherer7aced172000-08-15 01:13:23 +000025
Ezio Melotti4c6daf12010-08-02 20:40:20 +000026from idlelib.EditorWindow import EditorWindow, fixwordbreaks
27from idlelib.FileList import FileList
28from idlelib.ColorDelegator import ColorDelegator
29from idlelib.UndoDelegator import UndoDelegator
30from idlelib.OutputWindow import OutputWindow
31from idlelib.configHandler import idleConf
32from idlelib import idlever
33from idlelib import rpc
34from idlelib import Debugger
35from idlelib import RemoteDebugger
36from idlelib import macosxSupport
Chui Tey5d2af632002-05-26 13:36:41 +000037
Kurt B. Kaiserb9764192002-09-23 04:10:37 +000038IDENTCHARS = string.ascii_letters + string.digits + "_"
Kurt B. Kaiser24d7e0c2003-06-05 23:51:29 +000039LOCALHOST = '127.0.0.1'
Kurt B. Kaiserb9764192002-09-23 04:10:37 +000040
Kurt B. Kaisera00050f2003-05-08 20:26:55 +000041try:
42 from signal import SIGTERM
43except ImportError:
44 SIGTERM = 15
45
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000046# Override warnings module to write to warning_stream. Initialize to send IDLE
47# internal warnings to the console. ScriptBinding.check_syntax() will
48# temporarily redirect the stream to the shell window to display warnings when
49# checking user's code.
50global warning_stream
51warning_stream = sys.__stderr__
Chui Tey5d2af632002-05-26 13:36:41 +000052try:
53 import warnings
54except ImportError:
55 pass
56else:
Benjamin Peterson352ebae2008-10-16 19:46:25 +000057 def idle_showwarning(message, category, filename, lineno,
58 file=None, line=None):
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000059 file = warning_stream
60 try:
Benjamin Peterson352ebae2008-10-16 19:46:25 +000061 file.write(warnings.formatwarning(message, category, filename,\
62 lineno, file=file, line=line))
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000063 except IOError:
64 pass ## file (probably __stderr__) is invalid, warning dropped.
Chui Tey5d2af632002-05-26 13:36:41 +000065 warnings.showwarning = idle_showwarning
Benjamin Peterson352ebae2008-10-16 19:46:25 +000066 def idle_formatwarning(message, category, filename, lineno,
67 file=None, line=None):
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000068 """Format warnings the IDLE way"""
69 s = "\nWarning (from warnings module):\n"
70 s += ' File \"%s\", line %s\n' % (filename, lineno)
Benjamin Peterson352ebae2008-10-16 19:46:25 +000071 line = linecache.getline(filename, lineno).strip() \
72 if line is None else line
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000073 if line:
74 s += " %s\n" % line
75 s += "%s: %s\n>>> " % (category.__name__, message)
76 return s
77 warnings.formatwarning = idle_formatwarning
Chui Tey5d2af632002-05-26 13:36:41 +000078
Kurt B. Kaiserf7a88992004-11-13 21:05:58 +000079def extended_linecache_checkcache(filename=None,
80 orig_checkcache=linecache.checkcache):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +000081 """Extend linecache.checkcache to preserve the <pyshell#...> entries
82
Kurt B. Kaiserf7a88992004-11-13 21:05:58 +000083 Rather than repeating the linecache code, patch it to save the
84 <pyshell#...> entries, call the original linecache.checkcache()
85 (which destroys them), and then restore the saved entries.
86
87 orig_checkcache is bound at definition time to the original
88 method, allowing it to be patched.
Kurt B. Kaiser45186c42002-10-23 04:48:08 +000089
90 """
David Scherer7aced172000-08-15 01:13:23 +000091 cache = linecache.cache
92 save = {}
93 for filename in cache.keys():
94 if filename[:1] + filename[-1:] == '<>':
95 save[filename] = cache[filename]
96 orig_checkcache()
97 cache.update(save)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +000098
Kurt B. Kaiser81885592002-11-29 22:10:53 +000099# Patch linecache.checkcache():
100linecache.checkcache = extended_linecache_checkcache
David Scherer7aced172000-08-15 01:13:23 +0000101
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000102
David Scherer7aced172000-08-15 01:13:23 +0000103class PyShellEditorWindow(EditorWindow):
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000104 "Regular text edit window in IDLE, supports breakpoints"
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000105
David Scherer7aced172000-08-15 01:13:23 +0000106 def __init__(self, *args):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000107 self.breakpoints = []
Raymond Hettinger931237e2003-07-09 18:48:24 +0000108 EditorWindow.__init__(self, *args)
David Scherer7aced172000-08-15 01:13:23 +0000109 self.text.bind("<<set-breakpoint-here>>", self.set_breakpoint_here)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000110 self.text.bind("<<clear-breakpoint-here>>", self.clear_breakpoint_here)
David Scherer7aced172000-08-15 01:13:23 +0000111 self.text.bind("<<open-python-shell>>", self.flist.open_shell)
112
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000113 self.breakpointPath = os.path.join(idleConf.GetUserCfgDir(),
114 'breakpoints.lst')
Chui Teya2adb0f2002-11-04 22:14:54 +0000115 # whenever a file is changed, restore breakpoints
116 if self.io.filename: self.restore_file_breaks()
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000117 def filename_changed_hook(old_hook=self.io.filename_change_hook,
118 self=self):
Chui Teya2adb0f2002-11-04 22:14:54 +0000119 self.restore_file_breaks()
120 old_hook()
121 self.io.set_filename_change_hook(filename_changed_hook)
122
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000123 rmenu_specs = [("Set Breakpoint", "<<set-breakpoint-here>>"),
124 ("Clear Breakpoint", "<<clear-breakpoint-here>>")]
David Scherer7aced172000-08-15 01:13:23 +0000125
Chui Teya2adb0f2002-11-04 22:14:54 +0000126 def set_breakpoint(self, lineno):
127 text = self.text
128 filename = self.io.filename
129 text.tag_add("BREAK", "%d.0" % lineno, "%d.0" % (lineno+1))
130 try:
131 i = self.breakpoints.index(lineno)
132 except ValueError: # only add if missing, i.e. do once
133 self.breakpoints.append(lineno)
134 try: # update the subprocess debugger
135 debug = self.flist.pyshell.interp.debugger
136 debug.set_breakpoint_here(filename, lineno)
137 except: # but debugger may not be active right now....
138 pass
139
David Scherer7aced172000-08-15 01:13:23 +0000140 def set_breakpoint_here(self, event=None):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000141 text = self.text
142 filename = self.io.filename
143 if not filename:
144 text.bell()
David Scherer7aced172000-08-15 01:13:23 +0000145 return
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000146 lineno = int(float(text.index("insert")))
Chui Teya2adb0f2002-11-04 22:14:54 +0000147 self.set_breakpoint(lineno)
David Scherer7aced172000-08-15 01:13:23 +0000148
Kurt B. Kaiser669f4c32002-06-20 04:01:47 +0000149 def clear_breakpoint_here(self, event=None):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000150 text = self.text
151 filename = self.io.filename
152 if not filename:
153 text.bell()
Kurt B. Kaiser669f4c32002-06-20 04:01:47 +0000154 return
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000155 lineno = int(float(text.index("insert")))
156 try:
157 self.breakpoints.remove(lineno)
158 except:
159 pass
160 text.tag_remove("BREAK", "insert linestart",\
161 "insert lineend +1char")
162 try:
163 debug = self.flist.pyshell.interp.debugger
164 debug.clear_breakpoint_here(filename, lineno)
165 except:
166 pass
167
168 def clear_file_breaks(self):
169 if self.breakpoints:
170 text = self.text
171 filename = self.io.filename
172 if not filename:
173 text.bell()
174 return
175 self.breakpoints = []
176 text.tag_remove("BREAK", "1.0", END)
177 try:
178 debug = self.flist.pyshell.interp.debugger
179 debug.clear_file_breaks(filename)
180 except:
181 pass
182
Chui Teya2adb0f2002-11-04 22:14:54 +0000183 def store_file_breaks(self):
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000184 "Save breakpoints when file is saved"
185 # XXX 13 Dec 2002 KBK Currently the file must be saved before it can
186 # be run. The breaks are saved at that time. If we introduce
187 # a temporary file save feature the save breaks functionality
188 # needs to be re-verified, since the breaks at the time the
189 # temp file is created may differ from the breaks at the last
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000190 # permanent save of the file. Currently, a break introduced
191 # after a save will be effective, but not persistent.
192 # This is necessary to keep the saved breaks synched with the
193 # saved file.
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000194 #
195 # Breakpoints are set as tagged ranges in the text. Certain
196 # kinds of edits cause these ranges to be deleted: Inserting
197 # or deleting a line just before a breakpoint, and certain
198 # deletions prior to a breakpoint. These issues need to be
199 # investigated and understood. It's not clear if they are
200 # Tk issues or IDLE issues, or whether they can actually
201 # be fixed. Since a modified file has to be saved before it is
202 # run, and since self.breakpoints (from which the subprocess
203 # debugger is loaded) is updated during the save, the visible
204 # breaks stay synched with the subprocess even if one of these
205 # unexpected breakpoint deletions occurs.
206 breaks = self.breakpoints
207 filename = self.io.filename
Chui Teya2adb0f2002-11-04 22:14:54 +0000208 try:
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000209 lines = open(self.breakpointPath,"r").readlines()
Chui Teya2adb0f2002-11-04 22:14:54 +0000210 except IOError:
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000211 lines = []
212 new_file = open(self.breakpointPath,"w")
Chui Teya2adb0f2002-11-04 22:14:54 +0000213 for line in lines:
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000214 if not line.startswith(filename + '='):
Chui Teya2adb0f2002-11-04 22:14:54 +0000215 new_file.write(line)
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000216 self.update_breakpoints()
217 breaks = self.breakpoints
218 if breaks:
219 new_file.write(filename + '=' + str(breaks) + '\n')
Chui Teya2adb0f2002-11-04 22:14:54 +0000220 new_file.close()
221
222 def restore_file_breaks(self):
223 self.text.update() # this enables setting "BREAK" tags to be visible
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000224 filename = self.io.filename
225 if filename is None:
226 return
Chui Tey69371d62002-11-04 23:39:45 +0000227 if os.path.isfile(self.breakpointPath):
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000228 lines = open(self.breakpointPath,"r").readlines()
Chui Tey69371d62002-11-04 23:39:45 +0000229 for line in lines:
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000230 if line.startswith(filename + '='):
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000231 breakpoint_linenumbers = eval(line[len(filename)+1:])
Chui Tey69371d62002-11-04 23:39:45 +0000232 for breakpoint_linenumber in breakpoint_linenumbers:
233 self.set_breakpoint(breakpoint_linenumber)
Chui Teya2adb0f2002-11-04 22:14:54 +0000234
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000235 def update_breakpoints(self):
236 "Retrieves all the breakpoints in the current window"
Chui Teya2adb0f2002-11-04 22:14:54 +0000237 text = self.text
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000238 ranges = text.tag_ranges("BREAK")
239 linenumber_list = self.ranges_to_linenumbers(ranges)
240 self.breakpoints = linenumber_list
241
242 def ranges_to_linenumbers(self, ranges):
243 lines = []
244 for index in range(0, len(ranges), 2):
245 lineno = int(float(ranges[index]))
246 end = int(float(ranges[index+1]))
247 while lineno < end:
248 lines.append(lineno)
249 lineno += 1
250 return lines
251
Kurt B. Kaiser11220fa2002-12-24 00:57:22 +0000252# XXX 13 Dec 2002 KBK Not used currently
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000253# def saved_change_hook(self):
254# "Extend base method - clear breaks if module is modified"
255# if not self.get_saved():
256# self.clear_file_breaks()
257# EditorWindow.saved_change_hook(self)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000258
259 def _close(self):
260 "Extend base method - clear breaks when module is closed"
261 self.clear_file_breaks()
262 EditorWindow._close(self)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000263
David Scherer7aced172000-08-15 01:13:23 +0000264
265class PyShellFileList(FileList):
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000266 "Extend base class: IDLE supports a shell and breakpoints"
David Scherer7aced172000-08-15 01:13:23 +0000267
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000268 # override FileList's class variable, instances return PyShellEditorWindow
269 # instead of EditorWindow when new edit windows are created.
David Scherer7aced172000-08-15 01:13:23 +0000270 EditorWindow = PyShellEditorWindow
271
272 pyshell = None
273
274 def open_shell(self, event=None):
275 if self.pyshell:
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000276 self.pyshell.top.wakeup()
David Scherer7aced172000-08-15 01:13:23 +0000277 else:
278 self.pyshell = PyShell(self)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000279 if self.pyshell:
280 if not self.pyshell.begin():
281 return None
David Scherer7aced172000-08-15 01:13:23 +0000282 return self.pyshell
283
284
285class ModifiedColorDelegator(ColorDelegator):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000286 "Extend base class: colorizer for the shell window itself"
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000287
Steven M. Gavab77d3432002-03-02 07:16:21 +0000288 def __init__(self):
289 ColorDelegator.__init__(self)
290 self.LoadTagDefs()
David Scherer7aced172000-08-15 01:13:23 +0000291
292 def recolorize_main(self):
293 self.tag_remove("TODO", "1.0", "iomark")
294 self.tag_add("SYNC", "1.0", "iomark")
295 ColorDelegator.recolorize_main(self)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000296
Steven M. Gavab77d3432002-03-02 07:16:21 +0000297 def LoadTagDefs(self):
298 ColorDelegator.LoadTagDefs(self)
299 theme = idleConf.GetOption('main','Theme','name')
300 self.tagdefs.update({
301 "stdin": {'background':None,'foreground':None},
302 "stdout": idleConf.GetHighlight(theme, "stdout"),
303 "stderr": idleConf.GetHighlight(theme, "stderr"),
304 "console": idleConf.GetHighlight(theme, "console"),
Steven M. Gavab77d3432002-03-02 07:16:21 +0000305 })
David Scherer7aced172000-08-15 01:13:23 +0000306
David Scherer7aced172000-08-15 01:13:23 +0000307class ModifiedUndoDelegator(UndoDelegator):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000308 "Extend base class: forbid insert/delete before the I/O mark"
David Scherer7aced172000-08-15 01:13:23 +0000309
310 def insert(self, index, chars, tags=None):
311 try:
312 if self.delegate.compare(index, "<", "iomark"):
313 self.delegate.bell()
314 return
315 except TclError:
316 pass
317 UndoDelegator.insert(self, index, chars, tags)
318
319 def delete(self, index1, index2=None):
320 try:
321 if self.delegate.compare(index1, "<", "iomark"):
322 self.delegate.bell()
323 return
324 except TclError:
325 pass
326 UndoDelegator.delete(self, index1, index2)
327
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000328
329class MyRPCClient(rpc.RPCClient):
330
331 def handle_EOF(self):
332 "Override the base class - just re-raise EOFError"
333 raise EOFError
334
Kurt B. Kaiser8d1f11b2003-05-26 22:20:34 +0000335
David Scherer7aced172000-08-15 01:13:23 +0000336class ModifiedInterpreter(InteractiveInterpreter):
337
338 def __init__(self, tkconsole):
339 self.tkconsole = tkconsole
340 locals = sys.modules['__main__'].__dict__
341 InteractiveInterpreter.__init__(self, locals=locals)
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000342 self.save_warnings_filters = None
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000343 self.restarting = False
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000344 self.subprocess_arglist = self.build_subprocess_arglist()
David Scherer7aced172000-08-15 01:13:23 +0000345
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000346 port = 8833
Chui Tey5d2af632002-05-26 13:36:41 +0000347 rpcclt = None
348 rpcpid = None
349
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000350 def spawn_subprocess(self):
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000351 args = self.subprocess_arglist
Kurt B. Kaiserb7855182003-08-14 14:54:28 +0000352 self.rpcpid = os.spawnv(os.P_NOWAIT, sys.executable, args)
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000353
Tony Lowndsf53dec22002-12-20 04:24:43 +0000354 def build_subprocess_arglist(self):
Tony Lownds2398d572003-05-13 15:28:21 +0000355 w = ['-W' + s for s in sys.warnoptions]
Georg Brandld0761532006-10-12 07:57:21 +0000356 if 1/2 > 0: # account for new division
357 w.append('-Qnew')
Tony Lownds2398d572003-05-13 15:28:21 +0000358 # Maybe IDLE is installed and is being accessed via sys.path,
359 # or maybe it's not installed and the idle.py script is being
360 # run from the IDLE source directory.
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000361 del_exitf = idleConf.GetOption('main', 'General', 'delete-exitfunc',
362 default=False, type='bool')
Tony Lownds2398d572003-05-13 15:28:21 +0000363 if __name__ == 'idlelib.PyShell':
Walter Dörwald70a6b492004-02-12 17:35:32 +0000364 command = "__import__('idlelib.run').run.main(%r)" % (del_exitf,)
Tony Lowndsf2324b92002-09-29 00:34:10 +0000365 else:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000366 command = "__import__('run').main(%r)" % (del_exitf,)
Kurt B. Kaiserb7855182003-08-14 14:54:28 +0000367 if sys.platform[:3] == 'win' and ' ' in sys.executable:
368 # handle embedded space in path by quoting the argument
369 decorated_exec = '"%s"' % sys.executable
370 else:
371 decorated_exec = sys.executable
372 return [decorated_exec] + w + ["-c", command, str(self.port)]
Tony Lowndsf2324b92002-09-29 00:34:10 +0000373
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000374 def start_subprocess(self):
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000375 # spawning first avoids passing a listening socket to the subprocess
376 self.spawn_subprocess()
377 #time.sleep(20) # test to simulate GUI not accepting connection
Kurt B. Kaiser24d7e0c2003-06-05 23:51:29 +0000378 addr = (LOCALHOST, self.port)
Kurt B. Kaiser8dcdb772002-08-05 03:52:10 +0000379 # Idle starts listening for connection on localhost
Kurt B. Kaiser5db48432003-05-15 03:40:51 +0000380 for i in range(3):
Chui Tey5d2af632002-05-26 13:36:41 +0000381 time.sleep(i)
382 try:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000383 self.rpcclt = MyRPCClient(addr)
Chui Tey5d2af632002-05-26 13:36:41 +0000384 break
385 except socket.error, err:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000386 pass
Chui Tey5d2af632002-05-26 13:36:41 +0000387 else:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000388 self.display_port_binding_error()
389 return None
Kurt B. Kaiserb4179362002-07-26 00:06:42 +0000390 # Accept the connection from the Python execution server
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000391 self.rpcclt.listening_sock.settimeout(10)
392 try:
393 self.rpcclt.accept()
394 except socket.timeout, err:
395 self.display_no_subprocess_error()
396 return None
Kurt B. Kaiser969de452002-06-12 03:28:57 +0000397 self.rpcclt.register("stdin", self.tkconsole)
398 self.rpcclt.register("stdout", self.tkconsole.stdout)
399 self.rpcclt.register("stderr", self.tkconsole.stderr)
Chui Tey5d2af632002-05-26 13:36:41 +0000400 self.rpcclt.register("flist", self.tkconsole.flist)
Kurt B. Kaiser8cd0def2003-01-31 05:06:43 +0000401 self.rpcclt.register("linecache", linecache)
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000402 self.rpcclt.register("interp", self)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000403 self.transfer_path()
Chui Tey5d2af632002-05-26 13:36:41 +0000404 self.poll_subprocess()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000405 return self.rpcclt
Chui Tey5d2af632002-05-26 13:36:41 +0000406
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000407 def restart_subprocess(self):
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000408 if self.restarting:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000409 return self.rpcclt
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000410 self.restarting = True
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000411 # close only the subprocess debugger
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000412 debug = self.getdebugger()
413 if debug:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000414 try:
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000415 # Only close subprocess debugger, don't unregister gui_adap!
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000416 RemoteDebugger.close_subprocess_debugger(self.rpcclt)
417 except:
418 pass
419 # Kill subprocess, spawn a new one, accept connection.
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000420 self.rpcclt.close()
421 self.unix_terminate()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000422 console = self.tkconsole
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000423 was_executing = console.executing
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000424 console.executing = False
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000425 self.spawn_subprocess()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000426 try:
427 self.rpcclt.accept()
428 except socket.timeout, err:
429 self.display_no_subprocess_error()
430 return None
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000431 self.transfer_path()
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000432 # annotate restart in shell window and mark it
Kurt B. Kaiser4cc5ef52003-01-22 00:23:23 +0000433 console.text.delete("iomark", "end-1c")
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000434 if was_executing:
435 console.write('\n')
436 console.showprompt()
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000437 halfbar = ((int(console.width) - 16) // 2) * '='
438 console.write(halfbar + ' RESTART ' + halfbar)
439 console.text.mark_set("restart", "end-1c")
440 console.text.mark_gravity("restart", "left")
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000441 console.showprompt()
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000442 # restart subprocess debugger
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000443 if debug:
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000444 # Restarted debugger connects to current instance of debug GUI
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000445 gui = RemoteDebugger.restart_subprocess_debugger(self.rpcclt)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000446 # reload remote debugger breakpoints for all PyShellEditWindows
447 debug.load_breakpoints()
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000448 self.restarting = False
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000449 return self.rpcclt
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000450
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000451 def __request_interrupt(self):
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000452 self.rpcclt.remotecall("exec", "interrupt_the_server", (), {})
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000453
454 def interrupt_subprocess(self):
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000455 threading.Thread(target=self.__request_interrupt).start()
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000456
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000457 def kill_subprocess(self):
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000458 try:
459 self.rpcclt.close()
460 except AttributeError: # no socket
461 pass
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000462 self.unix_terminate()
463 self.tkconsole.executing = False
464 self.rpcclt = None
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000465
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000466 def unix_terminate(self):
467 "UNIX: make sure subprocess is terminated and collect status"
468 if hasattr(os, 'kill'):
469 try:
470 os.kill(self.rpcpid, SIGTERM)
471 except OSError:
472 # process already terminated:
473 return
474 else:
475 try:
476 os.waitpid(self.rpcpid, 0)
477 except OSError:
478 return
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000479
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000480 def transfer_path(self):
481 self.runcommand("""if 1:
482 import sys as _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +0000483 _sys.path = %r
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000484 del _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +0000485 \n""" % (sys.path,))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000486
Chui Tey5d2af632002-05-26 13:36:41 +0000487 active_seq = None
488
489 def poll_subprocess(self):
490 clt = self.rpcclt
491 if clt is None:
492 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000493 try:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000494 response = clt.pollresponse(self.active_seq, wait=0.05)
495 except (EOFError, IOError, KeyboardInterrupt):
496 # lost connection or subprocess terminated itself, restart
497 # [the KBI is from rpc.SocketIO.handle_EOF()]
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000498 if self.tkconsole.closing:
499 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000500 response = None
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000501 self.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000502 if response:
503 self.tkconsole.resetoutput()
504 self.active_seq = None
505 how, what = response
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000506 console = self.tkconsole.console
Chui Tey5d2af632002-05-26 13:36:41 +0000507 if how == "OK":
508 if what is not None:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000509 print >>console, repr(what)
Chui Tey5d2af632002-05-26 13:36:41 +0000510 elif how == "EXCEPTION":
Chui Tey5d2af632002-05-26 13:36:41 +0000511 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
512 self.remote_stack_viewer()
513 elif how == "ERROR":
Kurt B. Kaiser0930c432002-12-06 21:45:24 +0000514 errmsg = "PyShell.ModifiedInterpreter: Subprocess ERROR:\n"
515 print >>sys.__stderr__, errmsg, what
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000516 print >>console, errmsg, what
517 # we received a response to the currently active seq number:
Kurt B. Kaiserd112bc72006-08-16 05:01:42 +0000518 try:
519 self.tkconsole.endexecuting()
520 except AttributeError: # shell may have closed
521 pass
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000522 # Reschedule myself
523 if not self.tkconsole.closing:
524 self.tkconsole.text.after(self.tkconsole.pollinterval,
525 self.poll_subprocess)
Chui Tey5d2af632002-05-26 13:36:41 +0000526
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000527 debugger = None
528
529 def setdebugger(self, debugger):
530 self.debugger = debugger
531
532 def getdebugger(self):
533 return self.debugger
534
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000535 def open_remote_stack_viewer(self):
536 """Initiate the remote stack viewer from a separate thread.
537
538 This method is called from the subprocess, and by returning from this
539 method we allow the subprocess to unblock. After a bit the shell
540 requests the subprocess to open the remote stack viewer which returns a
Ezio Melotti1270bb92010-07-23 16:58:35 +0000541 static object looking at the last exception. It is queried through
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000542 the RPC mechanism.
543
544 """
545 self.tkconsole.text.after(300, self.remote_stack_viewer)
546 return
547
Chui Tey5d2af632002-05-26 13:36:41 +0000548 def remote_stack_viewer(self):
Ezio Melotti4c6daf12010-08-02 20:40:20 +0000549 from idlelib import RemoteObjectBrowser
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000550 oid = self.rpcclt.remotequeue("exec", "stackviewer", ("flist",), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000551 if oid is None:
552 self.tkconsole.root.bell()
553 return
554 item = RemoteObjectBrowser.StubObjectTreeItem(self.rpcclt, oid)
Ezio Melotti4c6daf12010-08-02 20:40:20 +0000555 from idlelib.TreeWidget import ScrolledCanvas, TreeNode
Chui Tey5d2af632002-05-26 13:36:41 +0000556 top = Toplevel(self.tkconsole.root)
Kurt B. Kaiser73360a32004-03-08 18:15:31 +0000557 theme = idleConf.GetOption('main','Theme','name')
558 background = idleConf.GetHighlight(theme, 'normal')['background']
559 sc = ScrolledCanvas(top, bg=background, highlightthickness=0)
Chui Tey5d2af632002-05-26 13:36:41 +0000560 sc.frame.pack(expand=1, fill="both")
561 node = TreeNode(sc.canvas, None, item)
562 node.expand()
563 # XXX Should GC the remote tree when closing the window
564
David Scherer7aced172000-08-15 01:13:23 +0000565 gid = 0
566
567 def execsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000568 "Like runsource() but assumes complete exec source"
David Scherer7aced172000-08-15 01:13:23 +0000569 filename = self.stuffsource(source)
570 self.execfile(filename, source)
571
572 def execfile(self, filename, source=None):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000573 "Execute an existing file"
David Scherer7aced172000-08-15 01:13:23 +0000574 if source is None:
575 source = open(filename, "r").read()
576 try:
577 code = compile(source, filename, "exec")
578 except (OverflowError, SyntaxError):
579 self.tkconsole.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000580 tkerr = self.tkconsole.stderr
581 print>>tkerr, '*** Error in script or command!\n'
582 print>>tkerr, 'Traceback (most recent call last):'
David Scherer7aced172000-08-15 01:13:23 +0000583 InteractiveInterpreter.showsyntaxerror(self, filename)
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000584 self.tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000585 else:
586 self.runcode(code)
587
588 def runsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000589 "Extend base class method: Stuff the source in the line cache first"
David Scherer7aced172000-08-15 01:13:23 +0000590 filename = self.stuffsource(source)
591 self.more = 0
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000592 self.save_warnings_filters = warnings.filters[:]
593 warnings.filterwarnings(action="error", category=SyntaxWarning)
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000594 if isinstance(source, types.UnicodeType):
Ezio Melotti4c6daf12010-08-02 20:40:20 +0000595 from idlelib import IOBinding
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000596 try:
597 source = source.encode(IOBinding.encoding)
598 except UnicodeError:
599 self.tkconsole.resetoutput()
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +0000600 self.write("Unsupported characters in input\n")
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000601 return
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000602 try:
Kurt B. Kaiser935ea9a2005-05-10 03:44:24 +0000603 # InteractiveInterpreter.runsource() calls its runcode() method,
604 # which is overridden (see below)
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000605 return InteractiveInterpreter.runsource(self, source, filename)
606 finally:
607 if self.save_warnings_filters is not None:
608 warnings.filters[:] = self.save_warnings_filters
609 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000610
611 def stuffsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000612 "Stuff source in the filename cache"
David Scherer7aced172000-08-15 01:13:23 +0000613 filename = "<pyshell#%d>" % self.gid
614 self.gid = self.gid + 1
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000615 lines = source.split("\n")
David Scherer7aced172000-08-15 01:13:23 +0000616 linecache.cache[filename] = len(source)+1, 0, lines, filename
617 return filename
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000618
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000619 def prepend_syspath(self, filename):
620 "Prepend sys.path with file's directory if not already included"
621 self.runcommand("""if 1:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000622 _filename = %r
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000623 import sys as _sys
624 from os.path import dirname as _dirname
625 _dir = _dirname(_filename)
626 if not _dir in _sys.path:
627 _sys.path.insert(0, _dir)
628 del _filename, _sys, _dirname, _dir
Walter Dörwald70a6b492004-02-12 17:35:32 +0000629 \n""" % (filename,))
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000630
David Scherer7aced172000-08-15 01:13:23 +0000631 def showsyntaxerror(self, filename=None):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000632 """Extend base class method: Add Colorizing
633
634 Color the offending position instead of printing it and pointing at it
635 with a caret.
636
637 """
David Scherer7aced172000-08-15 01:13:23 +0000638 text = self.tkconsole.text
639 stuff = self.unpackerror()
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000640 if stuff:
641 msg, lineno, offset, line = stuff
642 if lineno == 1:
643 pos = "iomark + %d chars" % (offset-1)
644 else:
645 pos = "iomark linestart + %d lines + %d chars" % \
646 (lineno-1, offset-1)
647 text.tag_add("ERROR", pos)
648 text.see(pos)
649 char = text.get(pos)
650 if char and char in IDENTCHARS:
651 text.tag_add("ERROR", pos + " wordstart", pos)
652 self.tkconsole.resetoutput()
653 self.write("SyntaxError: %s\n" % str(msg))
654 else:
David Scherer7aced172000-08-15 01:13:23 +0000655 self.tkconsole.resetoutput()
656 InteractiveInterpreter.showsyntaxerror(self, filename)
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000657 self.tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000658
659 def unpackerror(self):
660 type, value, tb = sys.exc_info()
661 ok = type is SyntaxError
662 if ok:
663 try:
664 msg, (dummy_filename, lineno, offset, line) = value
Kurt B. Kaiserbea57c62003-07-09 04:27:24 +0000665 if not offset:
666 offset = 0
David Scherer7aced172000-08-15 01:13:23 +0000667 except:
668 ok = 0
669 if ok:
670 return msg, lineno, offset, line
671 else:
672 return None
673
674 def showtraceback(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000675 "Extend base class method to reset output properly"
David Scherer7aced172000-08-15 01:13:23 +0000676 self.tkconsole.resetoutput()
677 self.checklinecache()
678 InteractiveInterpreter.showtraceback(self)
Chui Tey5d2af632002-05-26 13:36:41 +0000679 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
680 self.tkconsole.open_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +0000681
682 def checklinecache(self):
683 c = linecache.cache
684 for key in c.keys():
685 if key[:1] + key[-1:] != "<>":
686 del c[key]
687
Chui Tey5d2af632002-05-26 13:36:41 +0000688 def runcommand(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000689 "Run the code without invoking the debugger"
Chui Tey5d2af632002-05-26 13:36:41 +0000690 # The code better not raise an exception!
691 if self.tkconsole.executing:
Neal Norwitzf4c4f112002-11-30 18:49:10 +0000692 self.display_executing_dialog()
Chui Tey5d2af632002-05-26 13:36:41 +0000693 return 0
694 if self.rpcclt:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000695 self.rpcclt.remotequeue("exec", "runcode", (code,), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000696 else:
697 exec code in self.locals
698 return 1
699
David Scherer7aced172000-08-15 01:13:23 +0000700 def runcode(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000701 "Override base class method"
Chui Tey5d2af632002-05-26 13:36:41 +0000702 if self.tkconsole.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000703 self.interp.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000704 self.checklinecache()
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000705 if self.save_warnings_filters is not None:
706 warnings.filters[:] = self.save_warnings_filters
707 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000708 debugger = self.debugger
709 try:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000710 self.tkconsole.beginexecuting()
Kurt B. Kaiserdddeb0e2007-02-06 03:21:40 +0000711 if not debugger and self.rpcclt is not None:
712 self.active_seq = self.rpcclt.asyncqueue("exec", "runcode",
713 (code,), {})
714 elif debugger:
715 debugger.run(code, self.locals)
716 else:
717 exec code in self.locals
718 except SystemExit:
719 if not self.tkconsole.closing:
720 if tkMessageBox.askyesno(
721 "Exit?",
722 "Do you want to exit altogether?",
723 default="yes",
724 master=self.tkconsole.text):
Kurt B. Kaiserf137e1d2006-08-16 07:04:17 +0000725 raise
Kurt B. Kaiserdddeb0e2007-02-06 03:21:40 +0000726 else:
727 self.showtraceback()
728 else:
729 raise
730 except:
731 if use_subprocess:
732 print >>self.tkconsole.stderr, \
733 "IDLE internal error in runcode()"
David Scherer7aced172000-08-15 01:13:23 +0000734 self.showtraceback()
Kurt B. Kaiserdddeb0e2007-02-06 03:21:40 +0000735 self.tkconsole.endexecuting()
736 else:
737 if self.tkconsole.canceled:
738 self.tkconsole.canceled = False
739 print >>self.tkconsole.stderr, "KeyboardInterrupt"
740 else:
741 self.showtraceback()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000742 finally:
743 if not use_subprocess:
Kurt B. Kaiserd112bc72006-08-16 05:01:42 +0000744 try:
745 self.tkconsole.endexecuting()
746 except AttributeError: # shell may have closed
747 pass
David Scherer7aced172000-08-15 01:13:23 +0000748
749 def write(self, s):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000750 "Override base class method"
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000751 self.tkconsole.stderr.write(s)
David Scherer7aced172000-08-15 01:13:23 +0000752
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000753 def display_port_binding_error(self):
754 tkMessageBox.showerror(
755 "Port Binding Error",
756 "IDLE can't bind TCP/IP port 8833, which is necessary to "
757 "communicate with its Python execution server. Either "
758 "no networking is installed on this computer or another "
759 "process (another IDLE?) is using the port. Run IDLE with the -n "
760 "command line switch to start without a subprocess and refer to "
761 "Help/IDLE Help 'Running without a subprocess' for further "
762 "details.",
763 master=self.tkconsole.text)
764
765 def display_no_subprocess_error(self):
766 tkMessageBox.showerror(
767 "Subprocess Startup Error",
768 "IDLE's subprocess didn't make connection. Either IDLE can't "
769 "start a subprocess or personal firewall software is blocking "
770 "the connection.",
771 master=self.tkconsole.text)
772
773 def display_executing_dialog(self):
774 tkMessageBox.showerror(
775 "Already executing",
776 "The Python Shell window is already executing a command; "
777 "please wait until it is finished.",
778 master=self.tkconsole.text)
779
780
David Scherer7aced172000-08-15 01:13:23 +0000781class PyShell(OutputWindow):
782
783 shell_title = "Python Shell"
784
785 # Override classes
786 ColorDelegator = ModifiedColorDelegator
787 UndoDelegator = ModifiedUndoDelegator
788
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000789 # Override menus
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000790 menu_specs = [
791 ("file", "_File"),
792 ("edit", "_Edit"),
Kurt B. Kaiser4cc5ef52003-01-22 00:23:23 +0000793 ("debug", "_Debug"),
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000794 ("options", "_Options"),
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000795 ("windows", "_Windows"),
796 ("help", "_Help"),
797 ]
David Scherer7aced172000-08-15 01:13:23 +0000798
Ronald Oussoren19302d92006-06-11 14:33:36 +0000799 if macosxSupport.runningAsOSXApp():
800 del menu_specs[-3]
801 menu_specs[-2] = ("windows", "_Window")
802
803
David Scherer7aced172000-08-15 01:13:23 +0000804 # New classes
Ezio Melotti4c6daf12010-08-02 20:40:20 +0000805 from idlelib.IdleHistory import History
David Scherer7aced172000-08-15 01:13:23 +0000806
807 def __init__(self, flist=None):
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000808 if use_subprocess:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000809 ms = self.menu_specs
810 if ms[2][0] != "shell":
Kurt B. Kaiser7ae35482006-08-16 21:45:59 +0000811 ms.insert(2, ("shell", "She_ll"))
David Scherer7aced172000-08-15 01:13:23 +0000812 self.interp = ModifiedInterpreter(self)
813 if flist is None:
814 root = Tk()
815 fixwordbreaks(root)
816 root.withdraw()
817 flist = PyShellFileList(root)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000818 #
David Scherer7aced172000-08-15 01:13:23 +0000819 OutputWindow.__init__(self, flist, None, None)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000820 #
Kurt B. Kaiser6af44982005-01-19 00:22:59 +0000821## self.config(usetabs=1, indentwidth=8, context_use_ps1=1)
822 self.usetabs = True
823 # indentwidth must be 8 when using tabs. See note in EditorWindow:
824 self.indentwidth = 8
825 self.context_use_ps1 = True
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000826 #
David Scherer7aced172000-08-15 01:13:23 +0000827 text = self.text
828 text.configure(wrap="char")
829 text.bind("<<newline-and-indent>>", self.enter_callback)
830 text.bind("<<plain-newline-and-indent>>", self.linefeed_callback)
831 text.bind("<<interrupt-execution>>", self.cancel_callback)
David Scherer7aced172000-08-15 01:13:23 +0000832 text.bind("<<end-of-file>>", self.eof_callback)
833 text.bind("<<open-stack-viewer>>", self.open_stack_viewer)
Kurt B. Kaiser57bfe5d2003-05-10 00:09:52 +0000834 text.bind("<<toggle-debugger>>", self.toggle_debugger)
David Scherer7aced172000-08-15 01:13:23 +0000835 text.bind("<<toggle-jit-stack-viewer>>", self.toggle_jit_stack_viewer)
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000836 if use_subprocess:
837 text.bind("<<view-restart>>", self.view_restart_mark)
838 text.bind("<<restart-shell>>", self.restart_shell)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000839 #
David Scherer7aced172000-08-15 01:13:23 +0000840 self.save_stdout = sys.stdout
841 self.save_stderr = sys.stderr
842 self.save_stdin = sys.stdin
Ezio Melotti4c6daf12010-08-02 20:40:20 +0000843 from idlelib import IOBinding
Martin v. Löwisbcc651a2003-06-22 07:52:56 +0000844 self.stdout = PseudoFile(self, "stdout", IOBinding.encoding)
845 self.stderr = PseudoFile(self, "stderr", IOBinding.encoding)
846 self.console = PseudoFile(self, "console", IOBinding.encoding)
Chui Tey5d2af632002-05-26 13:36:41 +0000847 if not use_subprocess:
848 sys.stdout = self.stdout
849 sys.stderr = self.stderr
850 sys.stdin = self
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000851 #
David Scherer7aced172000-08-15 01:13:23 +0000852 self.history = self.History(self.text)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000853 #
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000854 self.pollinterval = 50 # millisec
Chui Tey5d2af632002-05-26 13:36:41 +0000855
Kurt B. Kaiser4d5bc602004-06-06 01:29:22 +0000856 def get_standard_extension_names(self):
857 return idleConf.GetExtensions(shell_only=True)
858
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000859 reading = False
860 executing = False
861 canceled = False
862 endoffile = False
863 closing = False
David Scherer7aced172000-08-15 01:13:23 +0000864
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +0000865 def set_warning_stream(self, stream):
Skip Montanarod9161422004-07-06 21:53:27 +0000866 global warning_stream
867 warning_stream = stream
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +0000868
869 def get_warning_stream(self):
870 return warning_stream
871
David Scherer7aced172000-08-15 01:13:23 +0000872 def toggle_debugger(self, event=None):
873 if self.executing:
874 tkMessageBox.showerror("Don't debug now",
875 "You can only toggle the debugger when idle",
876 master=self.text)
877 self.set_debugger_indicator()
878 return "break"
879 else:
880 db = self.interp.getdebugger()
881 if db:
882 self.close_debugger()
883 else:
884 self.open_debugger()
885
886 def set_debugger_indicator(self):
887 db = self.interp.getdebugger()
888 self.setvar("<<toggle-debugger>>", not not db)
889
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000890 def toggle_jit_stack_viewer(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +0000891 pass # All we need is the variable
892
893 def close_debugger(self):
894 db = self.interp.getdebugger()
895 if db:
896 self.interp.setdebugger(None)
897 db.close()
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000898 if self.interp.rpcclt:
899 RemoteDebugger.close_remote_debugger(self.interp.rpcclt)
David Scherer7aced172000-08-15 01:13:23 +0000900 self.resetoutput()
901 self.console.write("[DEBUG OFF]\n")
902 sys.ps1 = ">>> "
903 self.showprompt()
904 self.set_debugger_indicator()
905
906 def open_debugger(self):
Chui Tey5d2af632002-05-26 13:36:41 +0000907 if self.interp.rpcclt:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000908 dbg_gui = RemoteDebugger.start_remote_debugger(self.interp.rpcclt,
909 self)
910 else:
911 dbg_gui = Debugger.Debugger(self)
912 self.interp.setdebugger(dbg_gui)
913 dbg_gui.load_breakpoints()
Chui Tey5d2af632002-05-26 13:36:41 +0000914 sys.ps1 = "[DEBUG ON]\n>>> "
915 self.showprompt()
916 self.set_debugger_indicator()
917
David Scherer7aced172000-08-15 01:13:23 +0000918 def beginexecuting(self):
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000919 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +0000920 self.resetoutput()
921 self.executing = 1
David Scherer7aced172000-08-15 01:13:23 +0000922
923 def endexecuting(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000924 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +0000925 self.executing = 0
926 self.canceled = 0
Chui Tey5d2af632002-05-26 13:36:41 +0000927 self.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000928
929 def close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000930 "Extend EditorWindow.close()"
David Scherer7aced172000-08-15 01:13:23 +0000931 if self.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000932 response = tkMessageBox.askokcancel(
David Scherer7aced172000-08-15 01:13:23 +0000933 "Kill?",
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000934 "The program is still running!\n Do you want to kill it?",
David Scherer7aced172000-08-15 01:13:23 +0000935 default="ok",
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000936 parent=self.text)
Benjamin Peterson5b63acd2008-03-29 15:24:25 +0000937 if response is False:
David Scherer7aced172000-08-15 01:13:23 +0000938 return "cancel"
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +0000939 if self.reading:
940 self.top.quit()
941 self.canceled = True
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000942 self.closing = True
943 # Wait for poll_subprocess() rescheduling to stop
944 self.text.after(2 * self.pollinterval, self.close2)
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000945
946 def close2(self):
947 return EditorWindow.close(self)
David Scherer7aced172000-08-15 01:13:23 +0000948
949 def _close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000950 "Extend EditorWindow._close(), shut down debugger and execution server"
David Scherer7aced172000-08-15 01:13:23 +0000951 self.close_debugger()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000952 if use_subprocess:
953 self.interp.kill_subprocess()
David Scherer7aced172000-08-15 01:13:23 +0000954 # Restore std streams
955 sys.stdout = self.save_stdout
956 sys.stderr = self.save_stderr
957 sys.stdin = self.save_stdin
958 # Break cycles
959 self.interp = None
960 self.console = None
David Scherer7aced172000-08-15 01:13:23 +0000961 self.flist.pyshell = None
962 self.history = None
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000963 EditorWindow._close(self)
David Scherer7aced172000-08-15 01:13:23 +0000964
965 def ispythonsource(self, filename):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000966 "Override EditorWindow method: never remove the colorizer"
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000967 return True
David Scherer7aced172000-08-15 01:13:23 +0000968
969 def short_title(self):
970 return self.shell_title
971
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000972 COPYRIGHT = \
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000973 'Type "copyright", "credits" or "license()" for more information.'
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000974
Kurt B. Kaiser220fecf2003-07-27 03:24:19 +0000975 firewallmessage = """
976 ****************************************************************
977 Personal firewall software may warn about the connection IDLE
978 makes to its subprocess using this computer's internal loopback
979 interface. This connection is not visible on any external
980 interface and no data is sent to or received from the Internet.
981 ****************************************************************
982 """
983
David Scherer7aced172000-08-15 01:13:23 +0000984 def begin(self):
985 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000986 if use_subprocess:
987 nosub = ''
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000988 client = self.interp.start_subprocess()
989 if not client:
990 self.close()
Kurt B. Kaiser76637292004-01-21 22:10:01 +0000991 return False
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000992 else:
993 nosub = "==== No Subprocess ===="
Kurt B. Kaiser220fecf2003-07-27 03:24:19 +0000994 self.write("Python %s on %s\n%s\n%s\nIDLE %s %s\n" %
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000995 (sys.version, sys.platform, self.COPYRIGHT,
Kurt B. Kaiser220fecf2003-07-27 03:24:19 +0000996 self.firewallmessage, idlever.IDLE_VERSION, nosub))
David Scherer7aced172000-08-15 01:13:23 +0000997 self.showprompt()
Georg Brandl6634bf22008-05-20 07:13:37 +0000998 import Tkinter
999 Tkinter._default_root = None # 03Jan04 KBK What's this?
Kurt B. Kaiser76637292004-01-21 22:10:01 +00001000 return True
David Scherer7aced172000-08-15 01:13:23 +00001001
1002 def readline(self):
1003 save = self.reading
1004 try:
1005 self.reading = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001006 self.top.mainloop() # nested mainloop()
David Scherer7aced172000-08-15 01:13:23 +00001007 finally:
1008 self.reading = save
1009 line = self.text.get("iomark", "end-1c")
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001010 if len(line) == 0: # may be EOF if we quit our mainloop with Ctrl-C
1011 line = "\n"
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001012 if isinstance(line, unicode):
Ezio Melotti4c6daf12010-08-02 20:40:20 +00001013 from idlelib import IOBinding
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001014 try:
1015 line = line.encode(IOBinding.encoding)
1016 except UnicodeError:
1017 pass
David Scherer7aced172000-08-15 01:13:23 +00001018 self.resetoutput()
1019 if self.canceled:
1020 self.canceled = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001021 if not use_subprocess:
1022 raise KeyboardInterrupt
David Scherer7aced172000-08-15 01:13:23 +00001023 if self.endoffile:
1024 self.endoffile = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001025 line = ""
David Scherer7aced172000-08-15 01:13:23 +00001026 return line
1027
1028 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001029 return True
David Scherer7aced172000-08-15 01:13:23 +00001030
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001031 def cancel_callback(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +00001032 try:
1033 if self.text.compare("sel.first", "!=", "sel.last"):
1034 return # Active selection -- always use default binding
1035 except:
1036 pass
1037 if not (self.executing or self.reading):
1038 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001039 self.interp.write("KeyboardInterrupt\n")
David Scherer7aced172000-08-15 01:13:23 +00001040 self.showprompt()
1041 return "break"
1042 self.endoffile = 0
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001043 self.canceled = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001044 if (self.executing and self.interp.rpcclt):
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +00001045 if self.interp.getdebugger():
1046 self.interp.restart_subprocess()
1047 else:
1048 self.interp.interrupt_subprocess()
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001049 if self.reading:
1050 self.top.quit() # exit the nested mainloop() in readline()
David Scherer7aced172000-08-15 01:13:23 +00001051 return "break"
1052
1053 def eof_callback(self, event):
1054 if self.executing and not self.reading:
1055 return # Let the default binding (delete next char) take over
1056 if not (self.text.compare("iomark", "==", "insert") and
1057 self.text.compare("insert", "==", "end-1c")):
1058 return # Let the default binding (delete next char) take over
1059 if not self.executing:
David Scherer7aced172000-08-15 01:13:23 +00001060 self.resetoutput()
1061 self.close()
1062 else:
1063 self.canceled = 0
1064 self.endoffile = 1
1065 self.top.quit()
1066 return "break"
1067
David Scherer7aced172000-08-15 01:13:23 +00001068 def linefeed_callback(self, event):
1069 # Insert a linefeed without entering anything (still autoindented)
1070 if self.reading:
1071 self.text.insert("insert", "\n")
1072 self.text.see("insert")
1073 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001074 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001075 return "break"
1076
1077 def enter_callback(self, event):
1078 if self.executing and not self.reading:
1079 return # Let the default binding (insert '\n') take over
1080 # If some text is selected, recall the selection
1081 # (but only if this before the I/O mark)
1082 try:
1083 sel = self.text.get("sel.first", "sel.last")
1084 if sel:
1085 if self.text.compare("sel.last", "<=", "iomark"):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001086 self.recall(sel, event)
David Scherer7aced172000-08-15 01:13:23 +00001087 return "break"
1088 except:
1089 pass
1090 # If we're strictly before the line containing iomark, recall
1091 # the current line, less a leading prompt, less leading or
1092 # trailing whitespace
1093 if self.text.compare("insert", "<", "iomark linestart"):
1094 # Check if there's a relevant stdin range -- if so, use it
1095 prev = self.text.tag_prevrange("stdin", "insert")
1096 if prev and self.text.compare("insert", "<", prev[1]):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001097 self.recall(self.text.get(prev[0], prev[1]), event)
David Scherer7aced172000-08-15 01:13:23 +00001098 return "break"
1099 next = self.text.tag_nextrange("stdin", "insert")
1100 if next and self.text.compare("insert lineend", ">=", next[0]):
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001101 self.recall(self.text.get(next[0], next[1]), event)
David Scherer7aced172000-08-15 01:13:23 +00001102 return "break"
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001103 # No stdin mark -- just get the current line, less any prompt
Kurt B. Kaiserb1754452005-11-18 22:05:48 +00001104 indices = self.text.tag_nextrange("console", "insert linestart")
1105 if indices and \
1106 self.text.compare(indices[0], "<=", "insert linestart"):
1107 self.recall(self.text.get(indices[1], "insert lineend"), event)
1108 else:
1109 self.recall(self.text.get("insert linestart", "insert lineend"), event)
David Scherer7aced172000-08-15 01:13:23 +00001110 return "break"
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001111 # If we're between the beginning of the line and the iomark, i.e.
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001112 # in the prompt area, move to the end of the prompt
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001113 if self.text.compare("insert", "<", "iomark"):
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001114 self.text.mark_set("insert", "iomark")
David Scherer7aced172000-08-15 01:13:23 +00001115 # If we're in the current input and there's only whitespace
1116 # beyond the cursor, erase that whitespace first
1117 s = self.text.get("insert", "end-1c")
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001118 if s and not s.strip():
David Scherer7aced172000-08-15 01:13:23 +00001119 self.text.delete("insert", "end-1c")
1120 # If we're in the current input before its last line,
1121 # insert a newline right at the insert point
1122 if self.text.compare("insert", "<", "end-1c linestart"):
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001123 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001124 return "break"
1125 # We're in the last line; append a newline and submit it
1126 self.text.mark_set("insert", "end-1c")
1127 if self.reading:
1128 self.text.insert("insert", "\n")
1129 self.text.see("insert")
1130 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001131 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001132 self.text.tag_add("stdin", "iomark", "end-1c")
1133 self.text.update_idletasks()
1134 if self.reading:
1135 self.top.quit() # Break out of recursive mainloop() in raw_input()
1136 else:
1137 self.runit()
1138 return "break"
1139
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001140 def recall(self, s, event):
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001141 # remove leading and trailing empty or whitespace lines
1142 s = re.sub(r'^\s*\n', '' , s)
1143 s = re.sub(r'\n\s*$', '', s)
1144 lines = s.split('\n')
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001145 self.text.undo_block_start()
1146 try:
1147 self.text.tag_remove("sel", "1.0", "end")
1148 self.text.mark_set("insert", "end-1c")
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001149 prefix = self.text.get("insert linestart", "insert")
1150 if prefix.rstrip().endswith(':'):
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001151 self.newline_and_indent_event(event)
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001152 prefix = self.text.get("insert linestart", "insert")
1153 self.text.insert("insert", lines[0].strip())
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001154 if len(lines) > 1:
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001155 orig_base_indent = re.search(r'^([ \t]*)', lines[0]).group(0)
1156 new_base_indent = re.search(r'^([ \t]*)', prefix).group(0)
Kurt B. Kaiser8fa7eb52005-06-21 02:42:17 +00001157 for line in lines[1:]:
Kurt B. Kaisercd3d8be2006-08-10 17:11:09 +00001158 if line.startswith(orig_base_indent):
1159 # replace orig base indentation with new indentation
1160 line = new_base_indent + line[len(orig_base_indent):]
1161 self.text.insert('insert', '\n'+line.rstrip())
Kurt B. Kaisera7daba62005-06-19 18:56:15 +00001162 finally:
1163 self.text.see("insert")
1164 self.text.undo_block_stop()
David Scherer7aced172000-08-15 01:13:23 +00001165
1166 def runit(self):
1167 line = self.text.get("iomark", "end-1c")
1168 # Strip off last newline and surrounding whitespace.
1169 # (To allow you to hit return twice to end a statement.)
1170 i = len(line)
1171 while i > 0 and line[i-1] in " \t":
1172 i = i-1
1173 if i > 0 and line[i-1] == "\n":
1174 i = i-1
1175 while i > 0 and line[i-1] in " \t":
1176 i = i-1
1177 line = line[:i]
1178 more = self.interp.runsource(line)
David Scherer7aced172000-08-15 01:13:23 +00001179
David Scherer7aced172000-08-15 01:13:23 +00001180 def open_stack_viewer(self, event=None):
Chui Tey5d2af632002-05-26 13:36:41 +00001181 if self.interp.rpcclt:
1182 return self.interp.remote_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +00001183 try:
1184 sys.last_traceback
1185 except:
1186 tkMessageBox.showerror("No stack trace",
1187 "There is no stack trace yet.\n"
1188 "(sys.last_traceback is not defined)",
1189 master=self.text)
1190 return
Ezio Melotti4c6daf12010-08-02 20:40:20 +00001191 from idlelib.StackViewer import StackBrowser
David Scherer7aced172000-08-15 01:13:23 +00001192 sv = StackBrowser(self.root, self.flist)
1193
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001194 def view_restart_mark(self, event=None):
1195 self.text.see("iomark")
1196 self.text.see("restart")
1197
1198 def restart_shell(self, event=None):
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +00001199 self.interp.restart_subprocess()
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001200
David Scherer7aced172000-08-15 01:13:23 +00001201 def showprompt(self):
1202 self.resetoutput()
1203 try:
1204 s = str(sys.ps1)
1205 except:
1206 s = ""
1207 self.console.write(s)
1208 self.text.mark_set("insert", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001209 self.set_line_and_column()
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +00001210 self.io.reset_undo()
David Scherer7aced172000-08-15 01:13:23 +00001211
1212 def resetoutput(self):
1213 source = self.text.get("iomark", "end-1c")
1214 if self.history:
1215 self.history.history_store(source)
1216 if self.text.get("end-2c") != "\n":
1217 self.text.insert("end-1c", "\n")
1218 self.text.mark_set("iomark", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001219 self.set_line_and_column()
David Scherer7aced172000-08-15 01:13:23 +00001220 sys.stdout.softspace = 0
1221
1222 def write(self, s, tags=()):
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001223 try:
1224 self.text.mark_gravity("iomark", "right")
1225 OutputWindow.write(self, s, tags, "iomark")
1226 self.text.mark_gravity("iomark", "left")
1227 except:
1228 pass
David Scherer7aced172000-08-15 01:13:23 +00001229 if self.canceled:
1230 self.canceled = 0
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001231 if not use_subprocess:
1232 raise KeyboardInterrupt
David Scherer7aced172000-08-15 01:13:23 +00001233
Kurt B. Kaiserdcba6622004-12-21 22:10:32 +00001234class PseudoFile(object):
David Scherer7aced172000-08-15 01:13:23 +00001235
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001236 def __init__(self, shell, tags, encoding=None):
David Scherer7aced172000-08-15 01:13:23 +00001237 self.shell = shell
1238 self.tags = tags
Chui Tey5d2af632002-05-26 13:36:41 +00001239 self.softspace = 0
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001240 self.encoding = encoding
David Scherer7aced172000-08-15 01:13:23 +00001241
1242 def write(self, s):
1243 self.shell.write(s, self.tags)
1244
Ezio Melotti4c6daf12010-08-02 20:40:20 +00001245 def writelines(self, lines):
1246 for line in lines:
1247 self.write(line)
David Scherer7aced172000-08-15 01:13:23 +00001248
1249 def flush(self):
1250 pass
1251
1252 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001253 return True
David Scherer7aced172000-08-15 01:13:23 +00001254
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001255
David Scherer7aced172000-08-15 01:13:23 +00001256usage_msg = """\
David Scherer7aced172000-08-15 01:13:23 +00001257
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001258USAGE: idle [-deins] [-t title] [file]*
1259 idle [-dns] [-t title] (-c cmd | -r file) [arg]*
1260 idle [-dns] [-t title] - [arg]*
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001261
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001262 -h print this help message and exit
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001263 -n run IDLE without a subprocess (see Help/IDLE Help for details)
David Scherer7aced172000-08-15 01:13:23 +00001264
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001265The following options will override the IDLE 'settings' configuration:
Kurt B. Kaiser96d88422001-07-17 04:59:01 +00001266
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001267 -e open an edit window
1268 -i open a shell window
1269
1270The following options imply -i and will open a shell:
1271
1272 -c cmd run the command in a shell, or
1273 -r file run script from file
1274
1275 -d enable the debugger
1276 -s run $IDLESTARTUP or $PYTHONSTARTUP before anything else
1277 -t title set title of shell window
1278
1279A default edit window will be bypassed when -c, -r, or - are used.
1280
1281[arg]* are passed to the command (-c) or script (-r) in sys.argv[1:].
1282
1283Examples:
1284
1285idle
1286 Open an edit window or shell depending on IDLE's configuration.
1287
1288idle foo.py foobar.py
1289 Edit the files, also open a shell if configured to start with shell.
1290
1291idle -est "Baz" foo.py
1292 Run $IDLESTARTUP or $PYTHONSTARTUP, edit foo.py, and open a shell
1293 window with the title "Baz".
1294
1295idle -c "import sys; print sys.argv" "foo"
1296 Open a shell window and run the command, passing "-c" in sys.argv[0]
1297 and "foo" in sys.argv[1].
1298
1299idle -d -s -r foo.py "Hello World"
1300 Open a shell window, run a startup script, enable the debugger, and
1301 run foo.py, passing "foo.py" in sys.argv[0] and "Hello World" in
1302 sys.argv[1].
1303
1304echo "import sys; print sys.argv" | idle - "foobar"
1305 Open a shell window, run the script piped in, passing '' in sys.argv[0]
1306 and "foobar" in sys.argv[1].
David Scherer7aced172000-08-15 01:13:23 +00001307"""
1308
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001309def main():
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001310 global flist, root, use_subprocess
David Scherer7aced172000-08-15 01:13:23 +00001311
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001312 use_subprocess = True
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001313 enable_shell = False
1314 enable_edit = False
1315 debug = False
1316 cmd = None
1317 script = None
1318 startup = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001319 try:
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001320 opts, args = getopt.getopt(sys.argv[1:], "c:deihnr:st:")
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001321 except getopt.error, msg:
1322 sys.stderr.write("Error: %s\n" % str(msg))
1323 sys.stderr.write(usage_msg)
1324 sys.exit(2)
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001325 for o, a in opts:
1326 if o == '-c':
1327 cmd = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001328 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001329 if o == '-d':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001330 debug = True
1331 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001332 if o == '-e':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001333 enable_edit = True
1334 if o == '-h':
1335 sys.stdout.write(usage_msg)
1336 sys.exit()
1337 if o == '-i':
1338 enable_shell = True
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001339 if o == '-n':
1340 use_subprocess = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001341 if o == '-r':
1342 script = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001343 if os.path.isfile(script):
1344 pass
1345 else:
1346 print "No script file: ", script
1347 sys.exit()
1348 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001349 if o == '-s':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001350 startup = True
1351 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001352 if o == '-t':
1353 PyShell.shell_title = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001354 enable_shell = True
1355 if args and args[0] == '-':
1356 cmd = sys.stdin.read()
1357 enable_shell = True
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001358 # process sys.argv and sys.path:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001359 for i in range(len(sys.path)):
1360 sys.path[i] = os.path.abspath(sys.path[i])
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001361 if args and args[0] == '-':
1362 sys.argv = [''] + args[1:]
1363 elif cmd:
1364 sys.argv = ['-c'] + args
1365 elif script:
1366 sys.argv = [script] + args
1367 elif args:
1368 enable_edit = True
1369 pathx = []
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001370 for filename in args:
1371 pathx.append(os.path.dirname(filename))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001372 for dir in pathx:
1373 dir = os.path.abspath(dir)
Ezio Melotti4c6daf12010-08-02 20:40:20 +00001374 if dir not in sys.path:
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001375 sys.path.insert(0, dir)
Kurt B. Kaiserff002b92002-12-21 21:39:11 +00001376 else:
1377 dir = os.getcwd()
1378 if not dir in sys.path:
1379 sys.path.insert(0, dir)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001380 # check the IDLE settings configuration (but command line overrides)
1381 edit_start = idleConf.GetOption('main', 'General',
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001382 'editor-on-startup', type='bool')
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001383 enable_edit = enable_edit or edit_start
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001384 enable_shell = enable_shell or not edit_start
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001385 # start editor and/or shell windows:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001386 root = Tk(className="Idle")
Ronald Oussoren19302d92006-06-11 14:33:36 +00001387
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001388 fixwordbreaks(root)
1389 root.withdraw()
1390 flist = PyShellFileList(root)
Ronald Oussoren19302d92006-06-11 14:33:36 +00001391 macosxSupport.setupApp(root, flist)
1392
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001393 if enable_edit:
1394 if not (cmd or script):
1395 for filename in args:
1396 flist.open(filename)
1397 if not args:
1398 flist.new()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001399 if enable_shell:
Ronald Oussoren19302d92006-06-11 14:33:36 +00001400 shell = flist.open_shell()
1401 if not shell:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001402 return # couldn't open shell
Ronald Oussoren19302d92006-06-11 14:33:36 +00001403
1404 if macosxSupport.runningAsOSXApp() and flist.dict:
1405 # On OSX: when the user has double-clicked on a file that causes
Tim Peters4f96f1f2006-06-11 19:42:51 +00001406 # IDLE to be launched the shell window will open just in front of
1407 # the file she wants to see. Lower the interpreter window when
Ronald Oussoren19302d92006-06-11 14:33:36 +00001408 # there are open files.
1409 shell.top.lower()
1410
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001411 shell = flist.pyshell
1412 # handle remaining options:
1413 if debug:
1414 shell.open_debugger()
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001415 if startup:
1416 filename = os.environ.get("IDLESTARTUP") or \
1417 os.environ.get("PYTHONSTARTUP")
1418 if filename and os.path.isfile(filename):
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001419 shell.interp.execfile(filename)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001420 if shell and cmd or script:
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001421 shell.interp.runcommand("""if 1:
1422 import sys as _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001423 _sys.argv = %r
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001424 del _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001425 \n""" % (sys.argv,))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001426 if cmd:
1427 shell.interp.execsource(cmd)
1428 elif script:
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001429 shell.interp.prepend_syspath(script)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001430 shell.interp.execfile(script)
Ronald Oussoren19302d92006-06-11 14:33:36 +00001431
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001432 root.mainloop()
1433 root.destroy()
1434
David Scherer7aced172000-08-15 01:13:23 +00001435if __name__ == "__main__":
Kurt B. Kaiser9e8b8282003-06-15 17:38:45 +00001436 sys.modules['PyShell'] = sys.modules['__main__']
David Scherer7aced172000-08-15 01:13:23 +00001437 main()