blob: fecbf1ad547abc621cf07cd6b305826dafd135ba [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
Kurt B. Kaiser0930c432002-12-06 21:45:24 +000014import exceptions
David Scherer7aced172000-08-15 01:13:23 +000015
16import linecache
17from code import InteractiveInterpreter
18
Kurt B. Kaiser2303b1c2003-11-24 05:26:16 +000019try:
20 from Tkinter import *
21except ImportError:
22 print>>sys.__stderr__, "** IDLE can't import Tkinter. " \
23 "Your Python may not be configured for Tk. **"
24 sys.exit(1)
David Scherer7aced172000-08-15 01:13:23 +000025import tkMessageBox
26
27from EditorWindow import EditorWindow, fixwordbreaks
28from FileList import FileList
29from ColorDelegator import ColorDelegator
30from UndoDelegator import UndoDelegator
Kurt B. Kaiser969de452002-06-12 03:28:57 +000031from OutputWindow import OutputWindow
Steven M. Gava99300612001-11-04 07:03:08 +000032from configHandler import idleConf
David Scherer7aced172000-08-15 01:13:23 +000033import idlever
34
Chui Tey5d2af632002-05-26 13:36:41 +000035import rpc
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +000036import Debugger
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +000037import RemoteDebugger
Chui Tey5d2af632002-05-26 13:36:41 +000038
Kurt B. Kaiserb9764192002-09-23 04:10:37 +000039IDENTCHARS = string.ascii_letters + string.digits + "_"
Kurt B. Kaiser24d7e0c2003-06-05 23:51:29 +000040LOCALHOST = '127.0.0.1'
Kurt B. Kaiserb9764192002-09-23 04:10:37 +000041
Kurt B. Kaisera00050f2003-05-08 20:26:55 +000042try:
43 from signal import SIGTERM
44except ImportError:
45 SIGTERM = 15
46
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000047# Override warnings module to write to warning_stream. Initialize to send IDLE
48# internal warnings to the console. ScriptBinding.check_syntax() will
49# temporarily redirect the stream to the shell window to display warnings when
50# checking user's code.
51global warning_stream
52warning_stream = sys.__stderr__
Chui Tey5d2af632002-05-26 13:36:41 +000053try:
54 import warnings
55except ImportError:
56 pass
57else:
58 def idle_showwarning(message, category, filename, lineno):
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000059 file = warning_stream
60 try:
61 file.write(warnings.formatwarning(message, category, filename, lineno))
62 except IOError:
63 pass ## file (probably __stderr__) is invalid, warning dropped.
Chui Tey5d2af632002-05-26 13:36:41 +000064 warnings.showwarning = idle_showwarning
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000065 def idle_formatwarning(message, category, filename, lineno):
66 """Format warnings the IDLE way"""
67 s = "\nWarning (from warnings module):\n"
68 s += ' File \"%s\", line %s\n' % (filename, lineno)
69 line = linecache.getline(filename, lineno).strip()
70 if line:
71 s += " %s\n" % line
72 s += "%s: %s\n>>> " % (category.__name__, message)
73 return s
74 warnings.formatwarning = idle_formatwarning
Chui Tey5d2af632002-05-26 13:36:41 +000075
Kurt B. Kaiserf7a88992004-11-13 21:05:58 +000076def extended_linecache_checkcache(filename=None,
77 orig_checkcache=linecache.checkcache):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +000078 """Extend linecache.checkcache to preserve the <pyshell#...> entries
79
Kurt B. Kaiserf7a88992004-11-13 21:05:58 +000080 Rather than repeating the linecache code, patch it to save the
81 <pyshell#...> entries, call the original linecache.checkcache()
82 (which destroys them), and then restore the saved entries.
83
84 orig_checkcache is bound at definition time to the original
85 method, allowing it to be patched.
Kurt B. Kaiser45186c42002-10-23 04:48:08 +000086
87 """
David Scherer7aced172000-08-15 01:13:23 +000088 cache = linecache.cache
89 save = {}
90 for filename in cache.keys():
91 if filename[:1] + filename[-1:] == '<>':
92 save[filename] = cache[filename]
93 orig_checkcache()
94 cache.update(save)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +000095
Kurt B. Kaiser81885592002-11-29 22:10:53 +000096# Patch linecache.checkcache():
97linecache.checkcache = extended_linecache_checkcache
David Scherer7aced172000-08-15 01:13:23 +000098
Kurt B. Kaiser45186c42002-10-23 04:48:08 +000099
David Scherer7aced172000-08-15 01:13:23 +0000100class PyShellEditorWindow(EditorWindow):
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000101 "Regular text edit window in IDLE, supports breakpoints"
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000102
David Scherer7aced172000-08-15 01:13:23 +0000103 def __init__(self, *args):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000104 self.breakpoints = []
Raymond Hettinger931237e2003-07-09 18:48:24 +0000105 EditorWindow.__init__(self, *args)
David Scherer7aced172000-08-15 01:13:23 +0000106 self.text.bind("<<set-breakpoint-here>>", self.set_breakpoint_here)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000107 self.text.bind("<<clear-breakpoint-here>>", self.clear_breakpoint_here)
David Scherer7aced172000-08-15 01:13:23 +0000108 self.text.bind("<<open-python-shell>>", self.flist.open_shell)
109
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000110 self.breakpointPath = os.path.join(idleConf.GetUserCfgDir(),
111 'breakpoints.lst')
Chui Teya2adb0f2002-11-04 22:14:54 +0000112 # whenever a file is changed, restore breakpoints
113 if self.io.filename: self.restore_file_breaks()
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000114 def filename_changed_hook(old_hook=self.io.filename_change_hook,
115 self=self):
Chui Teya2adb0f2002-11-04 22:14:54 +0000116 self.restore_file_breaks()
117 old_hook()
118 self.io.set_filename_change_hook(filename_changed_hook)
119
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000120 rmenu_specs = [("Set Breakpoint", "<<set-breakpoint-here>>"),
121 ("Clear Breakpoint", "<<clear-breakpoint-here>>")]
David Scherer7aced172000-08-15 01:13:23 +0000122
Chui Teya2adb0f2002-11-04 22:14:54 +0000123 def set_breakpoint(self, lineno):
124 text = self.text
125 filename = self.io.filename
126 text.tag_add("BREAK", "%d.0" % lineno, "%d.0" % (lineno+1))
127 try:
128 i = self.breakpoints.index(lineno)
129 except ValueError: # only add if missing, i.e. do once
130 self.breakpoints.append(lineno)
131 try: # update the subprocess debugger
132 debug = self.flist.pyshell.interp.debugger
133 debug.set_breakpoint_here(filename, lineno)
134 except: # but debugger may not be active right now....
135 pass
136
David Scherer7aced172000-08-15 01:13:23 +0000137 def set_breakpoint_here(self, event=None):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000138 text = self.text
139 filename = self.io.filename
140 if not filename:
141 text.bell()
David Scherer7aced172000-08-15 01:13:23 +0000142 return
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000143 lineno = int(float(text.index("insert")))
Chui Teya2adb0f2002-11-04 22:14:54 +0000144 self.set_breakpoint(lineno)
David Scherer7aced172000-08-15 01:13:23 +0000145
Kurt B. Kaiser669f4c32002-06-20 04:01:47 +0000146 def clear_breakpoint_here(self, event=None):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000147 text = self.text
148 filename = self.io.filename
149 if not filename:
150 text.bell()
Kurt B. Kaiser669f4c32002-06-20 04:01:47 +0000151 return
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000152 lineno = int(float(text.index("insert")))
153 try:
154 self.breakpoints.remove(lineno)
155 except:
156 pass
157 text.tag_remove("BREAK", "insert linestart",\
158 "insert lineend +1char")
159 try:
160 debug = self.flist.pyshell.interp.debugger
161 debug.clear_breakpoint_here(filename, lineno)
162 except:
163 pass
164
165 def clear_file_breaks(self):
166 if self.breakpoints:
167 text = self.text
168 filename = self.io.filename
169 if not filename:
170 text.bell()
171 return
172 self.breakpoints = []
173 text.tag_remove("BREAK", "1.0", END)
174 try:
175 debug = self.flist.pyshell.interp.debugger
176 debug.clear_file_breaks(filename)
177 except:
178 pass
179
Chui Teya2adb0f2002-11-04 22:14:54 +0000180 def store_file_breaks(self):
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000181 "Save breakpoints when file is saved"
182 # XXX 13 Dec 2002 KBK Currently the file must be saved before it can
183 # be run. The breaks are saved at that time. If we introduce
184 # a temporary file save feature the save breaks functionality
185 # needs to be re-verified, since the breaks at the time the
186 # temp file is created may differ from the breaks at the last
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000187 # permanent save of the file. Currently, a break introduced
188 # after a save will be effective, but not persistent.
189 # This is necessary to keep the saved breaks synched with the
190 # saved file.
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000191 #
192 # Breakpoints are set as tagged ranges in the text. Certain
193 # kinds of edits cause these ranges to be deleted: Inserting
194 # or deleting a line just before a breakpoint, and certain
195 # deletions prior to a breakpoint. These issues need to be
196 # investigated and understood. It's not clear if they are
197 # Tk issues or IDLE issues, or whether they can actually
198 # be fixed. Since a modified file has to be saved before it is
199 # run, and since self.breakpoints (from which the subprocess
200 # debugger is loaded) is updated during the save, the visible
201 # breaks stay synched with the subprocess even if one of these
202 # unexpected breakpoint deletions occurs.
203 breaks = self.breakpoints
204 filename = self.io.filename
Chui Teya2adb0f2002-11-04 22:14:54 +0000205 try:
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000206 lines = open(self.breakpointPath,"r").readlines()
Chui Teya2adb0f2002-11-04 22:14:54 +0000207 except IOError:
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000208 lines = []
209 new_file = open(self.breakpointPath,"w")
Chui Teya2adb0f2002-11-04 22:14:54 +0000210 for line in lines:
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000211 if not line.startswith(filename + '='):
Chui Teya2adb0f2002-11-04 22:14:54 +0000212 new_file.write(line)
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000213 self.update_breakpoints()
214 breaks = self.breakpoints
215 if breaks:
216 new_file.write(filename + '=' + str(breaks) + '\n')
Chui Teya2adb0f2002-11-04 22:14:54 +0000217 new_file.close()
218
219 def restore_file_breaks(self):
220 self.text.update() # this enables setting "BREAK" tags to be visible
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000221 filename = self.io.filename
222 if filename is None:
223 return
Chui Tey69371d62002-11-04 23:39:45 +0000224 if os.path.isfile(self.breakpointPath):
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000225 lines = open(self.breakpointPath,"r").readlines()
Chui Tey69371d62002-11-04 23:39:45 +0000226 for line in lines:
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000227 if line.startswith(filename + '='):
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000228 breakpoint_linenumbers = eval(line[len(filename)+1:])
Chui Tey69371d62002-11-04 23:39:45 +0000229 for breakpoint_linenumber in breakpoint_linenumbers:
230 self.set_breakpoint(breakpoint_linenumber)
Chui Teya2adb0f2002-11-04 22:14:54 +0000231
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000232 def update_breakpoints(self):
233 "Retrieves all the breakpoints in the current window"
Chui Teya2adb0f2002-11-04 22:14:54 +0000234 text = self.text
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000235 ranges = text.tag_ranges("BREAK")
236 linenumber_list = self.ranges_to_linenumbers(ranges)
237 self.breakpoints = linenumber_list
238
239 def ranges_to_linenumbers(self, ranges):
240 lines = []
241 for index in range(0, len(ranges), 2):
242 lineno = int(float(ranges[index]))
243 end = int(float(ranges[index+1]))
244 while lineno < end:
245 lines.append(lineno)
246 lineno += 1
247 return lines
248
Kurt B. Kaiser11220fa2002-12-24 00:57:22 +0000249# XXX 13 Dec 2002 KBK Not used currently
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000250# def saved_change_hook(self):
251# "Extend base method - clear breaks if module is modified"
252# if not self.get_saved():
253# self.clear_file_breaks()
254# EditorWindow.saved_change_hook(self)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000255
256 def _close(self):
257 "Extend base method - clear breaks when module is closed"
258 self.clear_file_breaks()
259 EditorWindow._close(self)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000260
David Scherer7aced172000-08-15 01:13:23 +0000261
262class PyShellFileList(FileList):
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000263 "Extend base class: IDLE supports a shell and breakpoints"
David Scherer7aced172000-08-15 01:13:23 +0000264
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000265 # override FileList's class variable, instances return PyShellEditorWindow
266 # instead of EditorWindow when new edit windows are created.
David Scherer7aced172000-08-15 01:13:23 +0000267 EditorWindow = PyShellEditorWindow
268
269 pyshell = None
270
271 def open_shell(self, event=None):
272 if self.pyshell:
Kurt B. Kaiser183403a2004-08-22 05:14:32 +0000273 self.pyshell.top.wakeup()
David Scherer7aced172000-08-15 01:13:23 +0000274 else:
275 self.pyshell = PyShell(self)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000276 if self.pyshell:
277 if not self.pyshell.begin():
278 return None
David Scherer7aced172000-08-15 01:13:23 +0000279 return self.pyshell
280
281
282class ModifiedColorDelegator(ColorDelegator):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000283 "Extend base class: colorizer for the shell window itself"
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000284
Steven M. Gavab77d3432002-03-02 07:16:21 +0000285 def __init__(self):
286 ColorDelegator.__init__(self)
287 self.LoadTagDefs()
David Scherer7aced172000-08-15 01:13:23 +0000288
289 def recolorize_main(self):
290 self.tag_remove("TODO", "1.0", "iomark")
291 self.tag_add("SYNC", "1.0", "iomark")
292 ColorDelegator.recolorize_main(self)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000293
Steven M. Gavab77d3432002-03-02 07:16:21 +0000294 def LoadTagDefs(self):
295 ColorDelegator.LoadTagDefs(self)
296 theme = idleConf.GetOption('main','Theme','name')
297 self.tagdefs.update({
298 "stdin": {'background':None,'foreground':None},
299 "stdout": idleConf.GetHighlight(theme, "stdout"),
300 "stderr": idleConf.GetHighlight(theme, "stderr"),
301 "console": idleConf.GetHighlight(theme, "console"),
Steven M. Gavab77d3432002-03-02 07:16:21 +0000302 None: idleConf.GetHighlight(theme, "normal"),
303 })
David Scherer7aced172000-08-15 01:13:23 +0000304
David Scherer7aced172000-08-15 01:13:23 +0000305class ModifiedUndoDelegator(UndoDelegator):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000306 "Extend base class: forbid insert/delete before the I/O mark"
David Scherer7aced172000-08-15 01:13:23 +0000307
308 def insert(self, index, chars, tags=None):
309 try:
310 if self.delegate.compare(index, "<", "iomark"):
311 self.delegate.bell()
312 return
313 except TclError:
314 pass
315 UndoDelegator.insert(self, index, chars, tags)
316
317 def delete(self, index1, index2=None):
318 try:
319 if self.delegate.compare(index1, "<", "iomark"):
320 self.delegate.bell()
321 return
322 except TclError:
323 pass
324 UndoDelegator.delete(self, index1, index2)
325
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000326
327class MyRPCClient(rpc.RPCClient):
328
329 def handle_EOF(self):
330 "Override the base class - just re-raise EOFError"
331 raise EOFError
332
Kurt B. Kaiser8d1f11b2003-05-26 22:20:34 +0000333
David Scherer7aced172000-08-15 01:13:23 +0000334class ModifiedInterpreter(InteractiveInterpreter):
335
336 def __init__(self, tkconsole):
337 self.tkconsole = tkconsole
338 locals = sys.modules['__main__'].__dict__
339 InteractiveInterpreter.__init__(self, locals=locals)
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000340 self.save_warnings_filters = None
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000341 self.restarting = False
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000342 self.subprocess_arglist = self.build_subprocess_arglist()
David Scherer7aced172000-08-15 01:13:23 +0000343
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000344 port = 8833
Chui Tey5d2af632002-05-26 13:36:41 +0000345 rpcclt = None
346 rpcpid = None
347
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000348 def spawn_subprocess(self):
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000349 args = self.subprocess_arglist
Kurt B. Kaiserb7855182003-08-14 14:54:28 +0000350 self.rpcpid = os.spawnv(os.P_NOWAIT, sys.executable, args)
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000351
Tony Lowndsf53dec22002-12-20 04:24:43 +0000352 def build_subprocess_arglist(self):
Tony Lownds2398d572003-05-13 15:28:21 +0000353 w = ['-W' + s for s in sys.warnoptions]
354 # Maybe IDLE is installed and is being accessed via sys.path,
355 # or maybe it's not installed and the idle.py script is being
356 # run from the IDLE source directory.
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000357 del_exitf = idleConf.GetOption('main', 'General', 'delete-exitfunc',
358 default=False, type='bool')
Tony Lownds2398d572003-05-13 15:28:21 +0000359 if __name__ == 'idlelib.PyShell':
Walter Dörwald70a6b492004-02-12 17:35:32 +0000360 command = "__import__('idlelib.run').run.main(%r)" % (del_exitf,)
Tony Lowndsf2324b92002-09-29 00:34:10 +0000361 else:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000362 command = "__import__('run').main(%r)" % (del_exitf,)
Kurt B. Kaiserb7855182003-08-14 14:54:28 +0000363 if sys.platform[:3] == 'win' and ' ' in sys.executable:
364 # handle embedded space in path by quoting the argument
365 decorated_exec = '"%s"' % sys.executable
366 else:
367 decorated_exec = sys.executable
368 return [decorated_exec] + w + ["-c", command, str(self.port)]
Tony Lowndsf2324b92002-09-29 00:34:10 +0000369
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000370 def start_subprocess(self):
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000371 # spawning first avoids passing a listening socket to the subprocess
372 self.spawn_subprocess()
373 #time.sleep(20) # test to simulate GUI not accepting connection
Kurt B. Kaiser24d7e0c2003-06-05 23:51:29 +0000374 addr = (LOCALHOST, self.port)
Kurt B. Kaiser8dcdb772002-08-05 03:52:10 +0000375 # Idle starts listening for connection on localhost
Kurt B. Kaiser5db48432003-05-15 03:40:51 +0000376 for i in range(3):
Chui Tey5d2af632002-05-26 13:36:41 +0000377 time.sleep(i)
378 try:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000379 self.rpcclt = MyRPCClient(addr)
Chui Tey5d2af632002-05-26 13:36:41 +0000380 break
381 except socket.error, err:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000382 pass
Chui Tey5d2af632002-05-26 13:36:41 +0000383 else:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000384 self.display_port_binding_error()
385 return None
Kurt B. Kaiserb4179362002-07-26 00:06:42 +0000386 # Accept the connection from the Python execution server
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000387 self.rpcclt.listening_sock.settimeout(10)
388 try:
389 self.rpcclt.accept()
390 except socket.timeout, err:
391 self.display_no_subprocess_error()
392 return None
Kurt B. Kaiser969de452002-06-12 03:28:57 +0000393 self.rpcclt.register("stdin", self.tkconsole)
394 self.rpcclt.register("stdout", self.tkconsole.stdout)
395 self.rpcclt.register("stderr", self.tkconsole.stderr)
Chui Tey5d2af632002-05-26 13:36:41 +0000396 self.rpcclt.register("flist", self.tkconsole.flist)
Kurt B. Kaiser8cd0def2003-01-31 05:06:43 +0000397 self.rpcclt.register("linecache", linecache)
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000398 self.rpcclt.register("interp", self)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000399 self.transfer_path()
Chui Tey5d2af632002-05-26 13:36:41 +0000400 self.poll_subprocess()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000401 return self.rpcclt
Chui Tey5d2af632002-05-26 13:36:41 +0000402
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000403 def restart_subprocess(self):
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000404 if self.restarting:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000405 return self.rpcclt
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000406 self.restarting = True
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000407 # close only the subprocess debugger
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000408 debug = self.getdebugger()
409 if debug:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000410 try:
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000411 # Only close subprocess debugger, don't unregister gui_adap!
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000412 RemoteDebugger.close_subprocess_debugger(self.rpcclt)
413 except:
414 pass
415 # Kill subprocess, spawn a new one, accept connection.
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000416 self.rpcclt.close()
417 self.unix_terminate()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000418 console = self.tkconsole
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000419 was_executing = console.executing
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000420 console.executing = False
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000421 self.spawn_subprocess()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000422 try:
423 self.rpcclt.accept()
424 except socket.timeout, err:
425 self.display_no_subprocess_error()
426 return None
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000427 self.transfer_path()
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000428 # annotate restart in shell window and mark it
Kurt B. Kaiser4cc5ef52003-01-22 00:23:23 +0000429 console.text.delete("iomark", "end-1c")
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000430 if was_executing:
431 console.write('\n')
432 console.showprompt()
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000433 halfbar = ((int(console.width) - 16) // 2) * '='
434 console.write(halfbar + ' RESTART ' + halfbar)
435 console.text.mark_set("restart", "end-1c")
436 console.text.mark_gravity("restart", "left")
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000437 console.showprompt()
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000438 # restart subprocess debugger
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000439 if debug:
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000440 # Restarted debugger connects to current instance of debug GUI
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000441 gui = RemoteDebugger.restart_subprocess_debugger(self.rpcclt)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000442 # reload remote debugger breakpoints for all PyShellEditWindows
443 debug.load_breakpoints()
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000444 self.restarting = False
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000445 return self.rpcclt
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000446
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000447 def __request_interrupt(self):
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000448 self.rpcclt.remotecall("exec", "interrupt_the_server", (), {})
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000449
450 def interrupt_subprocess(self):
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000451 threading.Thread(target=self.__request_interrupt).start()
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000452
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000453 def kill_subprocess(self):
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000454 try:
455 self.rpcclt.close()
456 except AttributeError: # no socket
457 pass
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000458 self.unix_terminate()
459 self.tkconsole.executing = False
460 self.rpcclt = None
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000461
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000462 def unix_terminate(self):
463 "UNIX: make sure subprocess is terminated and collect status"
464 if hasattr(os, 'kill'):
465 try:
466 os.kill(self.rpcpid, SIGTERM)
467 except OSError:
468 # process already terminated:
469 return
470 else:
471 try:
472 os.waitpid(self.rpcpid, 0)
473 except OSError:
474 return
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000475
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000476 def transfer_path(self):
477 self.runcommand("""if 1:
478 import sys as _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +0000479 _sys.path = %r
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000480 del _sys
Kurt B. Kaiserb2487332003-03-04 04:03:45 +0000481 _msg = 'Use File/Exit or your end-of-file key to quit IDLE'
482 __builtins__.quit = __builtins__.exit = _msg
483 del _msg
Walter Dörwald70a6b492004-02-12 17:35:32 +0000484 \n""" % (sys.path,))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000485
Chui Tey5d2af632002-05-26 13:36:41 +0000486 active_seq = None
487
488 def poll_subprocess(self):
489 clt = self.rpcclt
490 if clt is None:
491 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000492 try:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000493 response = clt.pollresponse(self.active_seq, wait=0.05)
494 except (EOFError, IOError, KeyboardInterrupt):
495 # lost connection or subprocess terminated itself, restart
496 # [the KBI is from rpc.SocketIO.handle_EOF()]
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000497 if self.tkconsole.closing:
498 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000499 response = None
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000500 self.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000501 if response:
502 self.tkconsole.resetoutput()
503 self.active_seq = None
504 how, what = response
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000505 console = self.tkconsole.console
Chui Tey5d2af632002-05-26 13:36:41 +0000506 if how == "OK":
507 if what is not None:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000508 print >>console, repr(what)
Chui Tey5d2af632002-05-26 13:36:41 +0000509 elif how == "EXCEPTION":
Chui Tey5d2af632002-05-26 13:36:41 +0000510 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
511 self.remote_stack_viewer()
512 elif how == "ERROR":
Kurt B. Kaiser0930c432002-12-06 21:45:24 +0000513 errmsg = "PyShell.ModifiedInterpreter: Subprocess ERROR:\n"
514 print >>sys.__stderr__, errmsg, what
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000515 print >>console, errmsg, what
516 # we received a response to the currently active seq number:
Chui Tey5d2af632002-05-26 13:36:41 +0000517 self.tkconsole.endexecuting()
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000518 # Reschedule myself
519 if not self.tkconsole.closing:
520 self.tkconsole.text.after(self.tkconsole.pollinterval,
521 self.poll_subprocess)
Chui Tey5d2af632002-05-26 13:36:41 +0000522
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000523 debugger = None
524
525 def setdebugger(self, debugger):
526 self.debugger = debugger
527
528 def getdebugger(self):
529 return self.debugger
530
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000531 def open_remote_stack_viewer(self):
532 """Initiate the remote stack viewer from a separate thread.
533
534 This method is called from the subprocess, and by returning from this
535 method we allow the subprocess to unblock. After a bit the shell
536 requests the subprocess to open the remote stack viewer which returns a
537 static object looking at the last exceptiopn. It is queried through
538 the RPC mechanism.
539
540 """
541 self.tkconsole.text.after(300, self.remote_stack_viewer)
542 return
543
Chui Tey5d2af632002-05-26 13:36:41 +0000544 def remote_stack_viewer(self):
545 import RemoteObjectBrowser
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000546 oid = self.rpcclt.remotequeue("exec", "stackviewer", ("flist",), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000547 if oid is None:
548 self.tkconsole.root.bell()
549 return
550 item = RemoteObjectBrowser.StubObjectTreeItem(self.rpcclt, oid)
551 from TreeWidget import ScrolledCanvas, TreeNode
552 top = Toplevel(self.tkconsole.root)
Kurt B. Kaiser73360a32004-03-08 18:15:31 +0000553 theme = idleConf.GetOption('main','Theme','name')
554 background = idleConf.GetHighlight(theme, 'normal')['background']
555 sc = ScrolledCanvas(top, bg=background, highlightthickness=0)
Chui Tey5d2af632002-05-26 13:36:41 +0000556 sc.frame.pack(expand=1, fill="both")
557 node = TreeNode(sc.canvas, None, item)
558 node.expand()
559 # XXX Should GC the remote tree when closing the window
560
David Scherer7aced172000-08-15 01:13:23 +0000561 gid = 0
562
563 def execsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000564 "Like runsource() but assumes complete exec source"
David Scherer7aced172000-08-15 01:13:23 +0000565 filename = self.stuffsource(source)
566 self.execfile(filename, source)
567
568 def execfile(self, filename, source=None):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000569 "Execute an existing file"
David Scherer7aced172000-08-15 01:13:23 +0000570 if source is None:
571 source = open(filename, "r").read()
572 try:
573 code = compile(source, filename, "exec")
574 except (OverflowError, SyntaxError):
575 self.tkconsole.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000576 tkerr = self.tkconsole.stderr
577 print>>tkerr, '*** Error in script or command!\n'
578 print>>tkerr, 'Traceback (most recent call last):'
David Scherer7aced172000-08-15 01:13:23 +0000579 InteractiveInterpreter.showsyntaxerror(self, filename)
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000580 self.tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000581 else:
582 self.runcode(code)
583
584 def runsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000585 "Extend base class method: Stuff the source in the line cache first"
David Scherer7aced172000-08-15 01:13:23 +0000586 filename = self.stuffsource(source)
587 self.more = 0
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000588 self.save_warnings_filters = warnings.filters[:]
589 warnings.filterwarnings(action="error", category=SyntaxWarning)
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000590 if isinstance(source, types.UnicodeType):
591 import IOBinding
592 try:
593 source = source.encode(IOBinding.encoding)
594 except UnicodeError:
595 self.tkconsole.resetoutput()
596 self.write("Unsupported characters in input")
597 return
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000598 try:
599 return InteractiveInterpreter.runsource(self, source, filename)
600 finally:
601 if self.save_warnings_filters is not None:
602 warnings.filters[:] = self.save_warnings_filters
603 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000604
605 def stuffsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000606 "Stuff source in the filename cache"
David Scherer7aced172000-08-15 01:13:23 +0000607 filename = "<pyshell#%d>" % self.gid
608 self.gid = self.gid + 1
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000609 lines = source.split("\n")
David Scherer7aced172000-08-15 01:13:23 +0000610 linecache.cache[filename] = len(source)+1, 0, lines, filename
611 return filename
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000612
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000613 def prepend_syspath(self, filename):
614 "Prepend sys.path with file's directory if not already included"
615 self.runcommand("""if 1:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000616 _filename = %r
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000617 import sys as _sys
618 from os.path import dirname as _dirname
619 _dir = _dirname(_filename)
620 if not _dir in _sys.path:
621 _sys.path.insert(0, _dir)
622 del _filename, _sys, _dirname, _dir
Walter Dörwald70a6b492004-02-12 17:35:32 +0000623 \n""" % (filename,))
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000624
David Scherer7aced172000-08-15 01:13:23 +0000625 def showsyntaxerror(self, filename=None):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000626 """Extend base class method: Add Colorizing
627
628 Color the offending position instead of printing it and pointing at it
629 with a caret.
630
631 """
David Scherer7aced172000-08-15 01:13:23 +0000632 text = self.tkconsole.text
633 stuff = self.unpackerror()
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000634 if stuff:
635 msg, lineno, offset, line = stuff
636 if lineno == 1:
637 pos = "iomark + %d chars" % (offset-1)
638 else:
639 pos = "iomark linestart + %d lines + %d chars" % \
640 (lineno-1, offset-1)
641 text.tag_add("ERROR", pos)
642 text.see(pos)
643 char = text.get(pos)
644 if char and char in IDENTCHARS:
645 text.tag_add("ERROR", pos + " wordstart", pos)
646 self.tkconsole.resetoutput()
647 self.write("SyntaxError: %s\n" % str(msg))
648 else:
David Scherer7aced172000-08-15 01:13:23 +0000649 self.tkconsole.resetoutput()
650 InteractiveInterpreter.showsyntaxerror(self, filename)
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000651 self.tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000652
653 def unpackerror(self):
654 type, value, tb = sys.exc_info()
655 ok = type is SyntaxError
656 if ok:
657 try:
658 msg, (dummy_filename, lineno, offset, line) = value
Kurt B. Kaiserbea57c62003-07-09 04:27:24 +0000659 if not offset:
660 offset = 0
David Scherer7aced172000-08-15 01:13:23 +0000661 except:
662 ok = 0
663 if ok:
664 return msg, lineno, offset, line
665 else:
666 return None
667
668 def showtraceback(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000669 "Extend base class method to reset output properly"
David Scherer7aced172000-08-15 01:13:23 +0000670 self.tkconsole.resetoutput()
671 self.checklinecache()
672 InteractiveInterpreter.showtraceback(self)
Chui Tey5d2af632002-05-26 13:36:41 +0000673 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
674 self.tkconsole.open_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +0000675
676 def checklinecache(self):
677 c = linecache.cache
678 for key in c.keys():
679 if key[:1] + key[-1:] != "<>":
680 del c[key]
681
Chui Tey5d2af632002-05-26 13:36:41 +0000682 def runcommand(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000683 "Run the code without invoking the debugger"
Chui Tey5d2af632002-05-26 13:36:41 +0000684 # The code better not raise an exception!
685 if self.tkconsole.executing:
Neal Norwitzf4c4f112002-11-30 18:49:10 +0000686 self.display_executing_dialog()
Chui Tey5d2af632002-05-26 13:36:41 +0000687 return 0
688 if self.rpcclt:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000689 self.rpcclt.remotequeue("exec", "runcode", (code,), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000690 else:
691 exec code in self.locals
692 return 1
693
David Scherer7aced172000-08-15 01:13:23 +0000694 def runcode(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000695 "Override base class method"
Chui Tey5d2af632002-05-26 13:36:41 +0000696 if self.tkconsole.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000697 self.interp.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000698 self.checklinecache()
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000699 if self.save_warnings_filters is not None:
700 warnings.filters[:] = self.save_warnings_filters
701 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000702 debugger = self.debugger
703 try:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000704 self.tkconsole.beginexecuting()
705 try:
706 if not debugger and self.rpcclt is not None:
707 self.active_seq = self.rpcclt.asyncqueue("exec", "runcode",
708 (code,), {})
709 elif debugger:
710 debugger.run(code, self.locals)
711 else:
712 exec code in self.locals
713 except SystemExit:
714 if tkMessageBox.askyesno(
715 "Exit?",
716 "Do you want to exit altogether?",
717 default="yes",
718 master=self.tkconsole.text):
719 raise
720 else:
721 self.showtraceback()
722 except:
David Scherer7aced172000-08-15 01:13:23 +0000723 self.showtraceback()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000724 finally:
725 if not use_subprocess:
726 self.tkconsole.endexecuting()
David Scherer7aced172000-08-15 01:13:23 +0000727
728 def write(self, s):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000729 "Override base class method"
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000730 self.tkconsole.stderr.write(s)
David Scherer7aced172000-08-15 01:13:23 +0000731
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000732 def display_port_binding_error(self):
733 tkMessageBox.showerror(
734 "Port Binding Error",
735 "IDLE can't bind TCP/IP port 8833, which is necessary to "
736 "communicate with its Python execution server. Either "
737 "no networking is installed on this computer or another "
738 "process (another IDLE?) is using the port. Run IDLE with the -n "
739 "command line switch to start without a subprocess and refer to "
740 "Help/IDLE Help 'Running without a subprocess' for further "
741 "details.",
742 master=self.tkconsole.text)
743
744 def display_no_subprocess_error(self):
745 tkMessageBox.showerror(
746 "Subprocess Startup Error",
747 "IDLE's subprocess didn't make connection. Either IDLE can't "
748 "start a subprocess or personal firewall software is blocking "
749 "the connection.",
750 master=self.tkconsole.text)
751
752 def display_executing_dialog(self):
753 tkMessageBox.showerror(
754 "Already executing",
755 "The Python Shell window is already executing a command; "
756 "please wait until it is finished.",
757 master=self.tkconsole.text)
758
759
David Scherer7aced172000-08-15 01:13:23 +0000760class PyShell(OutputWindow):
761
762 shell_title = "Python Shell"
763
764 # Override classes
765 ColorDelegator = ModifiedColorDelegator
766 UndoDelegator = ModifiedUndoDelegator
767
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000768 # Override menus
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000769 menu_specs = [
770 ("file", "_File"),
771 ("edit", "_Edit"),
Kurt B. Kaiser4cc5ef52003-01-22 00:23:23 +0000772 ("debug", "_Debug"),
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000773 ("options", "_Options"),
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000774 ("windows", "_Windows"),
775 ("help", "_Help"),
776 ]
David Scherer7aced172000-08-15 01:13:23 +0000777
778 # New classes
779 from IdleHistory import History
780
781 def __init__(self, flist=None):
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000782 if use_subprocess:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000783 ms = self.menu_specs
784 if ms[2][0] != "shell":
785 ms.insert(2, ("shell", "_Shell"))
David Scherer7aced172000-08-15 01:13:23 +0000786 self.interp = ModifiedInterpreter(self)
787 if flist is None:
788 root = Tk()
789 fixwordbreaks(root)
790 root.withdraw()
791 flist = PyShellFileList(root)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000792 #
David Scherer7aced172000-08-15 01:13:23 +0000793 OutputWindow.__init__(self, flist, None, None)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000794 #
David Scherer7aced172000-08-15 01:13:23 +0000795 import __builtin__
796 __builtin__.quit = __builtin__.exit = "To exit, type Ctrl-D."
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000797 #
Kurt B. Kaiser6af44982005-01-19 00:22:59 +0000798## self.config(usetabs=1, indentwidth=8, context_use_ps1=1)
799 self.usetabs = True
800 # indentwidth must be 8 when using tabs. See note in EditorWindow:
801 self.indentwidth = 8
802 self.context_use_ps1 = True
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000803 #
David Scherer7aced172000-08-15 01:13:23 +0000804 text = self.text
805 text.configure(wrap="char")
806 text.bind("<<newline-and-indent>>", self.enter_callback)
807 text.bind("<<plain-newline-and-indent>>", self.linefeed_callback)
808 text.bind("<<interrupt-execution>>", self.cancel_callback)
809 text.bind("<<beginning-of-line>>", self.home_callback)
810 text.bind("<<end-of-file>>", self.eof_callback)
811 text.bind("<<open-stack-viewer>>", self.open_stack_viewer)
Kurt B. Kaiser57bfe5d2003-05-10 00:09:52 +0000812 text.bind("<<toggle-debugger>>", self.toggle_debugger)
David Scherer7aced172000-08-15 01:13:23 +0000813 text.bind("<<toggle-jit-stack-viewer>>", self.toggle_jit_stack_viewer)
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000814 if use_subprocess:
815 text.bind("<<view-restart>>", self.view_restart_mark)
816 text.bind("<<restart-shell>>", self.restart_shell)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000817 #
David Scherer7aced172000-08-15 01:13:23 +0000818 self.save_stdout = sys.stdout
819 self.save_stderr = sys.stderr
820 self.save_stdin = sys.stdin
Martin v. Löwisbcc651a2003-06-22 07:52:56 +0000821 import IOBinding
822 self.stdout = PseudoFile(self, "stdout", IOBinding.encoding)
823 self.stderr = PseudoFile(self, "stderr", IOBinding.encoding)
824 self.console = PseudoFile(self, "console", IOBinding.encoding)
Chui Tey5d2af632002-05-26 13:36:41 +0000825 if not use_subprocess:
826 sys.stdout = self.stdout
827 sys.stderr = self.stderr
828 sys.stdin = self
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000829 #
David Scherer7aced172000-08-15 01:13:23 +0000830 self.history = self.History(self.text)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000831 #
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000832 self.pollinterval = 50 # millisec
Chui Tey5d2af632002-05-26 13:36:41 +0000833
Kurt B. Kaiser4d5bc602004-06-06 01:29:22 +0000834 def get_standard_extension_names(self):
835 return idleConf.GetExtensions(shell_only=True)
836
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000837 reading = False
838 executing = False
839 canceled = False
840 endoffile = False
841 closing = False
David Scherer7aced172000-08-15 01:13:23 +0000842
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +0000843 def set_warning_stream(self, stream):
Skip Montanarod9161422004-07-06 21:53:27 +0000844 global warning_stream
845 warning_stream = stream
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +0000846
847 def get_warning_stream(self):
848 return warning_stream
849
David Scherer7aced172000-08-15 01:13:23 +0000850 def toggle_debugger(self, event=None):
851 if self.executing:
852 tkMessageBox.showerror("Don't debug now",
853 "You can only toggle the debugger when idle",
854 master=self.text)
855 self.set_debugger_indicator()
856 return "break"
857 else:
858 db = self.interp.getdebugger()
859 if db:
860 self.close_debugger()
861 else:
862 self.open_debugger()
863
864 def set_debugger_indicator(self):
865 db = self.interp.getdebugger()
866 self.setvar("<<toggle-debugger>>", not not db)
867
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000868 def toggle_jit_stack_viewer(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +0000869 pass # All we need is the variable
870
871 def close_debugger(self):
872 db = self.interp.getdebugger()
873 if db:
874 self.interp.setdebugger(None)
875 db.close()
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000876 if self.interp.rpcclt:
877 RemoteDebugger.close_remote_debugger(self.interp.rpcclt)
David Scherer7aced172000-08-15 01:13:23 +0000878 self.resetoutput()
879 self.console.write("[DEBUG OFF]\n")
880 sys.ps1 = ">>> "
881 self.showprompt()
882 self.set_debugger_indicator()
883
884 def open_debugger(self):
Chui Tey5d2af632002-05-26 13:36:41 +0000885 if self.interp.rpcclt:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000886 dbg_gui = RemoteDebugger.start_remote_debugger(self.interp.rpcclt,
887 self)
888 else:
889 dbg_gui = Debugger.Debugger(self)
890 self.interp.setdebugger(dbg_gui)
891 dbg_gui.load_breakpoints()
Chui Tey5d2af632002-05-26 13:36:41 +0000892 sys.ps1 = "[DEBUG ON]\n>>> "
893 self.showprompt()
894 self.set_debugger_indicator()
895
David Scherer7aced172000-08-15 01:13:23 +0000896 def beginexecuting(self):
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000897 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +0000898 self.resetoutput()
899 self.executing = 1
David Scherer7aced172000-08-15 01:13:23 +0000900
901 def endexecuting(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000902 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +0000903 self.executing = 0
904 self.canceled = 0
Chui Tey5d2af632002-05-26 13:36:41 +0000905 self.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000906
907 def close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000908 "Extend EditorWindow.close()"
David Scherer7aced172000-08-15 01:13:23 +0000909 if self.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000910 response = tkMessageBox.askokcancel(
David Scherer7aced172000-08-15 01:13:23 +0000911 "Kill?",
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000912 "The program is still running!\n Do you want to kill it?",
David Scherer7aced172000-08-15 01:13:23 +0000913 default="ok",
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000914 parent=self.text)
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000915 if response == False:
David Scherer7aced172000-08-15 01:13:23 +0000916 return "cancel"
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +0000917 if self.reading:
918 self.top.quit()
919 self.canceled = True
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000920 self.closing = True
921 # Wait for poll_subprocess() rescheduling to stop
922 self.text.after(2 * self.pollinterval, self.close2)
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000923
924 def close2(self):
925 return EditorWindow.close(self)
David Scherer7aced172000-08-15 01:13:23 +0000926
927 def _close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000928 "Extend EditorWindow._close(), shut down debugger and execution server"
David Scherer7aced172000-08-15 01:13:23 +0000929 self.close_debugger()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000930 if use_subprocess:
931 self.interp.kill_subprocess()
David Scherer7aced172000-08-15 01:13:23 +0000932 # Restore std streams
933 sys.stdout = self.save_stdout
934 sys.stderr = self.save_stderr
935 sys.stdin = self.save_stdin
936 # Break cycles
937 self.interp = None
938 self.console = None
David Scherer7aced172000-08-15 01:13:23 +0000939 self.flist.pyshell = None
940 self.history = None
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000941 EditorWindow._close(self)
David Scherer7aced172000-08-15 01:13:23 +0000942
943 def ispythonsource(self, filename):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000944 "Override EditorWindow method: never remove the colorizer"
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000945 return True
David Scherer7aced172000-08-15 01:13:23 +0000946
947 def short_title(self):
948 return self.shell_title
949
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000950 COPYRIGHT = \
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000951 'Type "copyright", "credits" or "license()" for more information.'
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000952
Kurt B. Kaiser220fecf2003-07-27 03:24:19 +0000953 firewallmessage = """
954 ****************************************************************
955 Personal firewall software may warn about the connection IDLE
956 makes to its subprocess using this computer's internal loopback
957 interface. This connection is not visible on any external
958 interface and no data is sent to or received from the Internet.
959 ****************************************************************
960 """
961
David Scherer7aced172000-08-15 01:13:23 +0000962 def begin(self):
963 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000964 if use_subprocess:
965 nosub = ''
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000966 client = self.interp.start_subprocess()
967 if not client:
968 self.close()
Kurt B. Kaiser76637292004-01-21 22:10:01 +0000969 return False
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000970 else:
971 nosub = "==== No Subprocess ===="
Kurt B. Kaiser220fecf2003-07-27 03:24:19 +0000972 self.write("Python %s on %s\n%s\n%s\nIDLE %s %s\n" %
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000973 (sys.version, sys.platform, self.COPYRIGHT,
Kurt B. Kaiser220fecf2003-07-27 03:24:19 +0000974 self.firewallmessage, idlever.IDLE_VERSION, nosub))
David Scherer7aced172000-08-15 01:13:23 +0000975 self.showprompt()
976 import Tkinter
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000977 Tkinter._default_root = None # 03Jan04 KBK What's this?
Kurt B. Kaiser76637292004-01-21 22:10:01 +0000978 return True
David Scherer7aced172000-08-15 01:13:23 +0000979
980 def readline(self):
981 save = self.reading
982 try:
983 self.reading = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +0000984 self.top.mainloop() # nested mainloop()
David Scherer7aced172000-08-15 01:13:23 +0000985 finally:
986 self.reading = save
987 line = self.text.get("iomark", "end-1c")
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +0000988 if len(line) == 0: # may be EOF if we quit our mainloop with Ctrl-C
989 line = "\n"
Martin v. Löwisbcc651a2003-06-22 07:52:56 +0000990 if isinstance(line, unicode):
991 import IOBinding
992 try:
993 line = line.encode(IOBinding.encoding)
994 except UnicodeError:
995 pass
David Scherer7aced172000-08-15 01:13:23 +0000996 self.resetoutput()
997 if self.canceled:
998 self.canceled = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +0000999 if not use_subprocess:
1000 raise KeyboardInterrupt
David Scherer7aced172000-08-15 01:13:23 +00001001 if self.endoffile:
1002 self.endoffile = 0
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001003 line = ""
David Scherer7aced172000-08-15 01:13:23 +00001004 return line
1005
1006 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001007 return True
David Scherer7aced172000-08-15 01:13:23 +00001008
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001009 def cancel_callback(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +00001010 try:
1011 if self.text.compare("sel.first", "!=", "sel.last"):
1012 return # Active selection -- always use default binding
1013 except:
1014 pass
1015 if not (self.executing or self.reading):
1016 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001017 self.interp.write("KeyboardInterrupt\n")
David Scherer7aced172000-08-15 01:13:23 +00001018 self.showprompt()
1019 return "break"
1020 self.endoffile = 0
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001021 self.canceled = 1
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001022 if (self.executing and self.interp.rpcclt):
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +00001023 if self.interp.getdebugger():
1024 self.interp.restart_subprocess()
1025 else:
1026 self.interp.interrupt_subprocess()
Kurt B. Kaiser5c3df352004-12-23 04:20:59 +00001027 if self.reading:
1028 self.top.quit() # exit the nested mainloop() in readline()
David Scherer7aced172000-08-15 01:13:23 +00001029 return "break"
1030
1031 def eof_callback(self, event):
1032 if self.executing and not self.reading:
1033 return # Let the default binding (delete next char) take over
1034 if not (self.text.compare("iomark", "==", "insert") and
1035 self.text.compare("insert", "==", "end-1c")):
1036 return # Let the default binding (delete next char) take over
1037 if not self.executing:
David Scherer7aced172000-08-15 01:13:23 +00001038 self.resetoutput()
1039 self.close()
1040 else:
1041 self.canceled = 0
1042 self.endoffile = 1
1043 self.top.quit()
1044 return "break"
1045
1046 def home_callback(self, event):
1047 if event.state != 0 and event.keysym == "Home":
1048 return # <Modifier-Home>; fall back to class binding
1049 if self.text.compare("iomark", "<=", "insert") and \
1050 self.text.compare("insert linestart", "<=", "iomark"):
1051 self.text.mark_set("insert", "iomark")
1052 self.text.tag_remove("sel", "1.0", "end")
1053 self.text.see("insert")
1054 return "break"
1055
1056 def linefeed_callback(self, event):
1057 # Insert a linefeed without entering anything (still autoindented)
1058 if self.reading:
1059 self.text.insert("insert", "\n")
1060 self.text.see("insert")
1061 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001062 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001063 return "break"
1064
1065 def enter_callback(self, event):
1066 if self.executing and not self.reading:
1067 return # Let the default binding (insert '\n') take over
1068 # If some text is selected, recall the selection
1069 # (but only if this before the I/O mark)
1070 try:
1071 sel = self.text.get("sel.first", "sel.last")
1072 if sel:
1073 if self.text.compare("sel.last", "<=", "iomark"):
1074 self.recall(sel)
1075 return "break"
1076 except:
1077 pass
1078 # If we're strictly before the line containing iomark, recall
1079 # the current line, less a leading prompt, less leading or
1080 # trailing whitespace
1081 if self.text.compare("insert", "<", "iomark linestart"):
1082 # Check if there's a relevant stdin range -- if so, use it
1083 prev = self.text.tag_prevrange("stdin", "insert")
1084 if prev and self.text.compare("insert", "<", prev[1]):
1085 self.recall(self.text.get(prev[0], prev[1]))
1086 return "break"
1087 next = self.text.tag_nextrange("stdin", "insert")
1088 if next and self.text.compare("insert lineend", ">=", next[0]):
1089 self.recall(self.text.get(next[0], next[1]))
1090 return "break"
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001091 # No stdin mark -- just get the current line, less any prompt
1092 line = self.text.get("insert linestart", "insert lineend")
1093 last_line_of_prompt = sys.ps1.split('\n')[-1]
1094 if line.startswith(last_line_of_prompt):
1095 line = line[len(last_line_of_prompt):]
1096 self.recall(line)
David Scherer7aced172000-08-15 01:13:23 +00001097 return "break"
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001098 # If we're between the beginning of the line and the iomark, i.e.
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001099 # in the prompt area, move to the end of the prompt
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001100 if self.text.compare("insert", "<", "iomark"):
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001101 self.text.mark_set("insert", "iomark")
David Scherer7aced172000-08-15 01:13:23 +00001102 # If we're in the current input and there's only whitespace
1103 # beyond the cursor, erase that whitespace first
1104 s = self.text.get("insert", "end-1c")
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001105 if s and not s.strip():
David Scherer7aced172000-08-15 01:13:23 +00001106 self.text.delete("insert", "end-1c")
1107 # If we're in the current input before its last line,
1108 # insert a newline right at the insert point
1109 if self.text.compare("insert", "<", "end-1c linestart"):
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001110 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001111 return "break"
1112 # We're in the last line; append a newline and submit it
1113 self.text.mark_set("insert", "end-1c")
1114 if self.reading:
1115 self.text.insert("insert", "\n")
1116 self.text.see("insert")
1117 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001118 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001119 self.text.tag_add("stdin", "iomark", "end-1c")
1120 self.text.update_idletasks()
1121 if self.reading:
1122 self.top.quit() # Break out of recursive mainloop() in raw_input()
1123 else:
1124 self.runit()
1125 return "break"
1126
1127 def recall(self, s):
1128 if self.history:
1129 self.history.recall(s)
1130
1131 def runit(self):
1132 line = self.text.get("iomark", "end-1c")
1133 # Strip off last newline and surrounding whitespace.
1134 # (To allow you to hit return twice to end a statement.)
1135 i = len(line)
1136 while i > 0 and line[i-1] in " \t":
1137 i = i-1
1138 if i > 0 and line[i-1] == "\n":
1139 i = i-1
1140 while i > 0 and line[i-1] in " \t":
1141 i = i-1
1142 line = line[:i]
1143 more = self.interp.runsource(line)
David Scherer7aced172000-08-15 01:13:23 +00001144
David Scherer7aced172000-08-15 01:13:23 +00001145 def open_stack_viewer(self, event=None):
Chui Tey5d2af632002-05-26 13:36:41 +00001146 if self.interp.rpcclt:
1147 return self.interp.remote_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +00001148 try:
1149 sys.last_traceback
1150 except:
1151 tkMessageBox.showerror("No stack trace",
1152 "There is no stack trace yet.\n"
1153 "(sys.last_traceback is not defined)",
1154 master=self.text)
1155 return
1156 from StackViewer import StackBrowser
1157 sv = StackBrowser(self.root, self.flist)
1158
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001159 def view_restart_mark(self, event=None):
1160 self.text.see("iomark")
1161 self.text.see("restart")
1162
1163 def restart_shell(self, event=None):
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +00001164 self.interp.restart_subprocess()
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001165
David Scherer7aced172000-08-15 01:13:23 +00001166 def showprompt(self):
1167 self.resetoutput()
1168 try:
1169 s = str(sys.ps1)
1170 except:
1171 s = ""
1172 self.console.write(s)
1173 self.text.mark_set("insert", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001174 self.set_line_and_column()
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +00001175 self.io.reset_undo()
David Scherer7aced172000-08-15 01:13:23 +00001176
1177 def resetoutput(self):
1178 source = self.text.get("iomark", "end-1c")
1179 if self.history:
1180 self.history.history_store(source)
1181 if self.text.get("end-2c") != "\n":
1182 self.text.insert("end-1c", "\n")
1183 self.text.mark_set("iomark", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001184 self.set_line_and_column()
David Scherer7aced172000-08-15 01:13:23 +00001185 sys.stdout.softspace = 0
1186
1187 def write(self, s, tags=()):
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001188 try:
1189 self.text.mark_gravity("iomark", "right")
1190 OutputWindow.write(self, s, tags, "iomark")
1191 self.text.mark_gravity("iomark", "left")
1192 except:
1193 pass
David Scherer7aced172000-08-15 01:13:23 +00001194 if self.canceled:
1195 self.canceled = 0
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001196 if not use_subprocess:
1197 raise KeyboardInterrupt
David Scherer7aced172000-08-15 01:13:23 +00001198
Kurt B. Kaiserdcba6622004-12-21 22:10:32 +00001199class PseudoFile(object):
David Scherer7aced172000-08-15 01:13:23 +00001200
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001201 def __init__(self, shell, tags, encoding=None):
David Scherer7aced172000-08-15 01:13:23 +00001202 self.shell = shell
1203 self.tags = tags
Chui Tey5d2af632002-05-26 13:36:41 +00001204 self.softspace = 0
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001205 self.encoding = encoding
David Scherer7aced172000-08-15 01:13:23 +00001206
1207 def write(self, s):
1208 self.shell.write(s, self.tags)
1209
1210 def writelines(self, l):
1211 map(self.write, l)
1212
1213 def flush(self):
1214 pass
1215
1216 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001217 return True
David Scherer7aced172000-08-15 01:13:23 +00001218
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001219
David Scherer7aced172000-08-15 01:13:23 +00001220usage_msg = """\
David Scherer7aced172000-08-15 01:13:23 +00001221
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001222USAGE: idle [-deins] [-t title] [file]*
1223 idle [-dns] [-t title] (-c cmd | -r file) [arg]*
1224 idle [-dns] [-t title] - [arg]*
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001225
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001226 -h print this help message and exit
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001227 -n run IDLE without a subprocess (see Help/IDLE Help for details)
David Scherer7aced172000-08-15 01:13:23 +00001228
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001229The following options will override the IDLE 'settings' configuration:
Kurt B. Kaiser96d88422001-07-17 04:59:01 +00001230
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001231 -e open an edit window
1232 -i open a shell window
1233
1234The following options imply -i and will open a shell:
1235
1236 -c cmd run the command in a shell, or
1237 -r file run script from file
1238
1239 -d enable the debugger
1240 -s run $IDLESTARTUP or $PYTHONSTARTUP before anything else
1241 -t title set title of shell window
1242
1243A default edit window will be bypassed when -c, -r, or - are used.
1244
1245[arg]* are passed to the command (-c) or script (-r) in sys.argv[1:].
1246
1247Examples:
1248
1249idle
1250 Open an edit window or shell depending on IDLE's configuration.
1251
1252idle foo.py foobar.py
1253 Edit the files, also open a shell if configured to start with shell.
1254
1255idle -est "Baz" foo.py
1256 Run $IDLESTARTUP or $PYTHONSTARTUP, edit foo.py, and open a shell
1257 window with the title "Baz".
1258
1259idle -c "import sys; print sys.argv" "foo"
1260 Open a shell window and run the command, passing "-c" in sys.argv[0]
1261 and "foo" in sys.argv[1].
1262
1263idle -d -s -r foo.py "Hello World"
1264 Open a shell window, run a startup script, enable the debugger, and
1265 run foo.py, passing "foo.py" in sys.argv[0] and "Hello World" in
1266 sys.argv[1].
1267
1268echo "import sys; print sys.argv" | idle - "foobar"
1269 Open a shell window, run the script piped in, passing '' in sys.argv[0]
1270 and "foobar" in sys.argv[1].
David Scherer7aced172000-08-15 01:13:23 +00001271"""
1272
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001273def main():
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001274 global flist, root, use_subprocess
David Scherer7aced172000-08-15 01:13:23 +00001275
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001276 use_subprocess = True
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001277 enable_shell = False
1278 enable_edit = False
1279 debug = False
1280 cmd = None
1281 script = None
1282 startup = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001283 try:
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001284 sys.ps1
1285 except AttributeError:
1286 sys.ps1 = '>>> '
1287 try:
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001288 opts, args = getopt.getopt(sys.argv[1:], "c:deihnr:st:")
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001289 except getopt.error, msg:
1290 sys.stderr.write("Error: %s\n" % str(msg))
1291 sys.stderr.write(usage_msg)
1292 sys.exit(2)
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001293 for o, a in opts:
1294 if o == '-c':
1295 cmd = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001296 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001297 if o == '-d':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001298 debug = True
1299 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001300 if o == '-e':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001301 enable_edit = True
1302 if o == '-h':
1303 sys.stdout.write(usage_msg)
1304 sys.exit()
1305 if o == '-i':
1306 enable_shell = True
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001307 if o == '-n':
1308 use_subprocess = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001309 if o == '-r':
1310 script = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001311 if os.path.isfile(script):
1312 pass
1313 else:
1314 print "No script file: ", script
1315 sys.exit()
1316 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001317 if o == '-s':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001318 startup = True
1319 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001320 if o == '-t':
1321 PyShell.shell_title = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001322 enable_shell = True
1323 if args and args[0] == '-':
1324 cmd = sys.stdin.read()
1325 enable_shell = True
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001326 # process sys.argv and sys.path:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001327 for i in range(len(sys.path)):
1328 sys.path[i] = os.path.abspath(sys.path[i])
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001329 if args and args[0] == '-':
1330 sys.argv = [''] + args[1:]
1331 elif cmd:
1332 sys.argv = ['-c'] + args
1333 elif script:
1334 sys.argv = [script] + args
1335 elif args:
1336 enable_edit = True
1337 pathx = []
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001338 for filename in args:
1339 pathx.append(os.path.dirname(filename))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001340 for dir in pathx:
1341 dir = os.path.abspath(dir)
1342 if not dir in sys.path:
1343 sys.path.insert(0, dir)
Kurt B. Kaiserff002b92002-12-21 21:39:11 +00001344 else:
1345 dir = os.getcwd()
1346 if not dir in sys.path:
1347 sys.path.insert(0, dir)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001348 # check the IDLE settings configuration (but command line overrides)
1349 edit_start = idleConf.GetOption('main', 'General',
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001350 'editor-on-startup', type='bool')
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001351 enable_edit = enable_edit or edit_start
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001352 enable_shell = enable_shell or not edit_start
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001353 # start editor and/or shell windows:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001354 root = Tk(className="Idle")
1355 fixwordbreaks(root)
1356 root.withdraw()
1357 flist = PyShellFileList(root)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001358 if enable_edit:
1359 if not (cmd or script):
1360 for filename in args:
1361 flist.open(filename)
1362 if not args:
1363 flist.new()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001364 if enable_shell:
1365 if not flist.open_shell():
1366 return # couldn't open shell
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001367 shell = flist.pyshell
1368 # handle remaining options:
1369 if debug:
1370 shell.open_debugger()
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001371 if startup:
1372 filename = os.environ.get("IDLESTARTUP") or \
1373 os.environ.get("PYTHONSTARTUP")
1374 if filename and os.path.isfile(filename):
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001375 shell.interp.execfile(filename)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001376 if shell and cmd or script:
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001377 shell.interp.runcommand("""if 1:
1378 import sys as _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001379 _sys.argv = %r
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001380 del _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001381 \n""" % (sys.argv,))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001382 if cmd:
1383 shell.interp.execsource(cmd)
1384 elif script:
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001385 shell.interp.prepend_syspath(script)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001386 shell.interp.execfile(script)
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001387 root.mainloop()
1388 root.destroy()
1389
David Scherer7aced172000-08-15 01:13:23 +00001390if __name__ == "__main__":
Kurt B. Kaiser9e8b8282003-06-15 17:38:45 +00001391 sys.modules['PyShell'] = sys.modules['__main__']
David Scherer7aced172000-08-15 01:13:23 +00001392 main()