blob: 028e3ee0ea097611b122fb62713eda1aa2fae87b [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
Chui Tey5d2af632002-05-26 13:36:41 +000047# Change warnings module to write to sys.__stderr__
48try:
49 import warnings
50except ImportError:
51 pass
52else:
53 def idle_showwarning(message, category, filename, lineno):
54 file = sys.__stderr__
55 file.write(warnings.formatwarning(message, category, filename, lineno))
56 warnings.showwarning = idle_showwarning
57
Kurt B. Kaiser81885592002-11-29 22:10:53 +000058def extended_linecache_checkcache(orig_checkcache=linecache.checkcache):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +000059 """Extend linecache.checkcache to preserve the <pyshell#...> entries
60
Kurt B. Kaiser81885592002-11-29 22:10:53 +000061 Rather than repeating the linecache code, patch it to save the pyshell#
62 entries, call the original linecache.checkcache(), and then restore the
63 saved entries. Assigning the orig_checkcache keyword arg freezes its value
64 at definition time to the (original) method linecache.checkcache(), i.e.
65 makes orig_checkcache lexical.
Kurt B. Kaiser45186c42002-10-23 04:48:08 +000066
67 """
David Scherer7aced172000-08-15 01:13:23 +000068 cache = linecache.cache
69 save = {}
70 for filename in cache.keys():
71 if filename[:1] + filename[-1:] == '<>':
72 save[filename] = cache[filename]
73 orig_checkcache()
74 cache.update(save)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +000075
Kurt B. Kaiser81885592002-11-29 22:10:53 +000076# Patch linecache.checkcache():
77linecache.checkcache = extended_linecache_checkcache
David Scherer7aced172000-08-15 01:13:23 +000078
Kurt B. Kaiser45186c42002-10-23 04:48:08 +000079
David Scherer7aced172000-08-15 01:13:23 +000080class PyShellEditorWindow(EditorWindow):
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +000081 "Regular text edit window when a shell is present"
Kurt B. Kaiser45186c42002-10-23 04:48:08 +000082
David Scherer7aced172000-08-15 01:13:23 +000083 def __init__(self, *args):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +000084 self.breakpoints = []
Raymond Hettinger931237e2003-07-09 18:48:24 +000085 EditorWindow.__init__(self, *args)
David Scherer7aced172000-08-15 01:13:23 +000086 self.text.bind("<<set-breakpoint-here>>", self.set_breakpoint_here)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +000087 self.text.bind("<<clear-breakpoint-here>>", self.clear_breakpoint_here)
David Scherer7aced172000-08-15 01:13:23 +000088 self.text.bind("<<open-python-shell>>", self.flist.open_shell)
89
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +000090 self.breakpointPath = os.path.join(idleConf.GetUserCfgDir(),
91 'breakpoints.lst')
Chui Teya2adb0f2002-11-04 22:14:54 +000092 # whenever a file is changed, restore breakpoints
93 if self.io.filename: self.restore_file_breaks()
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +000094 def filename_changed_hook(old_hook=self.io.filename_change_hook,
95 self=self):
Chui Teya2adb0f2002-11-04 22:14:54 +000096 self.restore_file_breaks()
97 old_hook()
98 self.io.set_filename_change_hook(filename_changed_hook)
99
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000100 rmenu_specs = [("Set Breakpoint", "<<set-breakpoint-here>>"),
101 ("Clear Breakpoint", "<<clear-breakpoint-here>>")]
David Scherer7aced172000-08-15 01:13:23 +0000102
Chui Teya2adb0f2002-11-04 22:14:54 +0000103 def set_breakpoint(self, lineno):
104 text = self.text
105 filename = self.io.filename
106 text.tag_add("BREAK", "%d.0" % lineno, "%d.0" % (lineno+1))
107 try:
108 i = self.breakpoints.index(lineno)
109 except ValueError: # only add if missing, i.e. do once
110 self.breakpoints.append(lineno)
111 try: # update the subprocess debugger
112 debug = self.flist.pyshell.interp.debugger
113 debug.set_breakpoint_here(filename, lineno)
114 except: # but debugger may not be active right now....
115 pass
116
David Scherer7aced172000-08-15 01:13:23 +0000117 def set_breakpoint_here(self, event=None):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000118 text = self.text
119 filename = self.io.filename
120 if not filename:
121 text.bell()
David Scherer7aced172000-08-15 01:13:23 +0000122 return
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000123 lineno = int(float(text.index("insert")))
Chui Teya2adb0f2002-11-04 22:14:54 +0000124 self.set_breakpoint(lineno)
David Scherer7aced172000-08-15 01:13:23 +0000125
Kurt B. Kaiser669f4c32002-06-20 04:01:47 +0000126 def clear_breakpoint_here(self, event=None):
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000127 text = self.text
128 filename = self.io.filename
129 if not filename:
130 text.bell()
Kurt B. Kaiser669f4c32002-06-20 04:01:47 +0000131 return
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000132 lineno = int(float(text.index("insert")))
133 try:
134 self.breakpoints.remove(lineno)
135 except:
136 pass
137 text.tag_remove("BREAK", "insert linestart",\
138 "insert lineend +1char")
139 try:
140 debug = self.flist.pyshell.interp.debugger
141 debug.clear_breakpoint_here(filename, lineno)
142 except:
143 pass
144
145 def clear_file_breaks(self):
146 if self.breakpoints:
147 text = self.text
148 filename = self.io.filename
149 if not filename:
150 text.bell()
151 return
152 self.breakpoints = []
153 text.tag_remove("BREAK", "1.0", END)
154 try:
155 debug = self.flist.pyshell.interp.debugger
156 debug.clear_file_breaks(filename)
157 except:
158 pass
159
Chui Teya2adb0f2002-11-04 22:14:54 +0000160 def store_file_breaks(self):
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000161 "Save breakpoints when file is saved"
162 # XXX 13 Dec 2002 KBK Currently the file must be saved before it can
163 # be run. The breaks are saved at that time. If we introduce
164 # a temporary file save feature the save breaks functionality
165 # needs to be re-verified, since the breaks at the time the
166 # temp file is created may differ from the breaks at the last
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000167 # permanent save of the file. Currently, a break introduced
168 # after a save will be effective, but not persistent.
169 # This is necessary to keep the saved breaks synched with the
170 # saved file.
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000171 #
172 # Breakpoints are set as tagged ranges in the text. Certain
173 # kinds of edits cause these ranges to be deleted: Inserting
174 # or deleting a line just before a breakpoint, and certain
175 # deletions prior to a breakpoint. These issues need to be
176 # investigated and understood. It's not clear if they are
177 # Tk issues or IDLE issues, or whether they can actually
178 # be fixed. Since a modified file has to be saved before it is
179 # run, and since self.breakpoints (from which the subprocess
180 # debugger is loaded) is updated during the save, the visible
181 # breaks stay synched with the subprocess even if one of these
182 # unexpected breakpoint deletions occurs.
183 breaks = self.breakpoints
184 filename = self.io.filename
Chui Teya2adb0f2002-11-04 22:14:54 +0000185 try:
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000186 lines = open(self.breakpointPath,"r").readlines()
Chui Teya2adb0f2002-11-04 22:14:54 +0000187 except IOError:
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000188 lines = []
189 new_file = open(self.breakpointPath,"w")
Chui Teya2adb0f2002-11-04 22:14:54 +0000190 for line in lines:
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000191 if not line.startswith(filename + '='):
Chui Teya2adb0f2002-11-04 22:14:54 +0000192 new_file.write(line)
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000193 self.update_breakpoints()
194 breaks = self.breakpoints
195 if breaks:
196 new_file.write(filename + '=' + str(breaks) + '\n')
Chui Teya2adb0f2002-11-04 22:14:54 +0000197 new_file.close()
198
199 def restore_file_breaks(self):
200 self.text.update() # this enables setting "BREAK" tags to be visible
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000201 filename = self.io.filename
202 if filename is None:
203 return
Chui Tey69371d62002-11-04 23:39:45 +0000204 if os.path.isfile(self.breakpointPath):
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000205 lines = open(self.breakpointPath,"r").readlines()
Chui Tey69371d62002-11-04 23:39:45 +0000206 for line in lines:
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000207 if line.startswith(filename + '='):
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000208 breakpoint_linenumbers = eval(line[len(filename)+1:])
Chui Tey69371d62002-11-04 23:39:45 +0000209 for breakpoint_linenumber in breakpoint_linenumbers:
210 self.set_breakpoint(breakpoint_linenumber)
Chui Teya2adb0f2002-11-04 22:14:54 +0000211
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000212 def update_breakpoints(self):
213 "Retrieves all the breakpoints in the current window"
Chui Teya2adb0f2002-11-04 22:14:54 +0000214 text = self.text
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000215 ranges = text.tag_ranges("BREAK")
216 linenumber_list = self.ranges_to_linenumbers(ranges)
217 self.breakpoints = linenumber_list
218
219 def ranges_to_linenumbers(self, ranges):
220 lines = []
221 for index in range(0, len(ranges), 2):
222 lineno = int(float(ranges[index]))
223 end = int(float(ranges[index+1]))
224 while lineno < end:
225 lines.append(lineno)
226 lineno += 1
227 return lines
228
Kurt B. Kaiser11220fa2002-12-24 00:57:22 +0000229# XXX 13 Dec 2002 KBK Not used currently
Kurt B. Kaiserbfed3462002-12-14 04:38:51 +0000230# def saved_change_hook(self):
231# "Extend base method - clear breaks if module is modified"
232# if not self.get_saved():
233# self.clear_file_breaks()
234# EditorWindow.saved_change_hook(self)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000235
236 def _close(self):
237 "Extend base method - clear breaks when module is closed"
238 self.clear_file_breaks()
239 EditorWindow._close(self)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000240
David Scherer7aced172000-08-15 01:13:23 +0000241
242class PyShellFileList(FileList):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000243 "Extend base class: file list when a shell is present"
David Scherer7aced172000-08-15 01:13:23 +0000244
245 EditorWindow = PyShellEditorWindow
246
247 pyshell = None
248
249 def open_shell(self, event=None):
250 if self.pyshell:
251 self.pyshell.wakeup()
252 else:
253 self.pyshell = PyShell(self)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000254 if self.pyshell:
255 if not self.pyshell.begin():
256 return None
David Scherer7aced172000-08-15 01:13:23 +0000257 return self.pyshell
258
259
260class ModifiedColorDelegator(ColorDelegator):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000261 "Extend base class: colorizer for the shell window itself"
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000262
Steven M. Gavab77d3432002-03-02 07:16:21 +0000263 def __init__(self):
264 ColorDelegator.__init__(self)
265 self.LoadTagDefs()
David Scherer7aced172000-08-15 01:13:23 +0000266
267 def recolorize_main(self):
268 self.tag_remove("TODO", "1.0", "iomark")
269 self.tag_add("SYNC", "1.0", "iomark")
270 ColorDelegator.recolorize_main(self)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000271
Steven M. Gavab77d3432002-03-02 07:16:21 +0000272 def LoadTagDefs(self):
273 ColorDelegator.LoadTagDefs(self)
274 theme = idleConf.GetOption('main','Theme','name')
275 self.tagdefs.update({
276 "stdin": {'background':None,'foreground':None},
277 "stdout": idleConf.GetHighlight(theme, "stdout"),
278 "stderr": idleConf.GetHighlight(theme, "stderr"),
279 "console": idleConf.GetHighlight(theme, "console"),
Steven M. Gavab77d3432002-03-02 07:16:21 +0000280 None: idleConf.GetHighlight(theme, "normal"),
281 })
David Scherer7aced172000-08-15 01:13:23 +0000282
David Scherer7aced172000-08-15 01:13:23 +0000283class ModifiedUndoDelegator(UndoDelegator):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000284 "Extend base class: forbid insert/delete before the I/O mark"
David Scherer7aced172000-08-15 01:13:23 +0000285
286 def insert(self, index, chars, tags=None):
287 try:
288 if self.delegate.compare(index, "<", "iomark"):
289 self.delegate.bell()
290 return
291 except TclError:
292 pass
293 UndoDelegator.insert(self, index, chars, tags)
294
295 def delete(self, index1, index2=None):
296 try:
297 if self.delegate.compare(index1, "<", "iomark"):
298 self.delegate.bell()
299 return
300 except TclError:
301 pass
302 UndoDelegator.delete(self, index1, index2)
303
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000304
305class MyRPCClient(rpc.RPCClient):
306
307 def handle_EOF(self):
308 "Override the base class - just re-raise EOFError"
309 raise EOFError
310
Kurt B. Kaiser8d1f11b2003-05-26 22:20:34 +0000311
David Scherer7aced172000-08-15 01:13:23 +0000312class ModifiedInterpreter(InteractiveInterpreter):
313
314 def __init__(self, tkconsole):
315 self.tkconsole = tkconsole
316 locals = sys.modules['__main__'].__dict__
317 InteractiveInterpreter.__init__(self, locals=locals)
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000318 self.save_warnings_filters = None
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000319 self.restarting = False
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000320 self.subprocess_arglist = self.build_subprocess_arglist()
David Scherer7aced172000-08-15 01:13:23 +0000321
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000322 port = 8833
Chui Tey5d2af632002-05-26 13:36:41 +0000323 rpcclt = None
324 rpcpid = None
325
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000326 def spawn_subprocess(self):
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000327 args = self.subprocess_arglist
Kurt B. Kaiserb7855182003-08-14 14:54:28 +0000328 self.rpcpid = os.spawnv(os.P_NOWAIT, sys.executable, args)
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000329
Tony Lowndsf53dec22002-12-20 04:24:43 +0000330 def build_subprocess_arglist(self):
Tony Lownds2398d572003-05-13 15:28:21 +0000331 w = ['-W' + s for s in sys.warnoptions]
332 # Maybe IDLE is installed and is being accessed via sys.path,
333 # or maybe it's not installed and the idle.py script is being
334 # run from the IDLE source directory.
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000335 del_exitf = idleConf.GetOption('main', 'General', 'delete-exitfunc',
336 default=False, type='bool')
Tony Lownds2398d572003-05-13 15:28:21 +0000337 if __name__ == 'idlelib.PyShell':
Walter Dörwald70a6b492004-02-12 17:35:32 +0000338 command = "__import__('idlelib.run').run.main(%r)" % (del_exitf,)
Tony Lowndsf2324b92002-09-29 00:34:10 +0000339 else:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000340 command = "__import__('run').main(%r)" % (del_exitf,)
Kurt B. Kaiserb7855182003-08-14 14:54:28 +0000341 if sys.platform[:3] == 'win' and ' ' in sys.executable:
342 # handle embedded space in path by quoting the argument
343 decorated_exec = '"%s"' % sys.executable
344 else:
345 decorated_exec = sys.executable
346 return [decorated_exec] + w + ["-c", command, str(self.port)]
Tony Lowndsf2324b92002-09-29 00:34:10 +0000347
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000348 def start_subprocess(self):
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000349 # spawning first avoids passing a listening socket to the subprocess
350 self.spawn_subprocess()
351 #time.sleep(20) # test to simulate GUI not accepting connection
Kurt B. Kaiser24d7e0c2003-06-05 23:51:29 +0000352 addr = (LOCALHOST, self.port)
Kurt B. Kaiser8dcdb772002-08-05 03:52:10 +0000353 # Idle starts listening for connection on localhost
Kurt B. Kaiser5db48432003-05-15 03:40:51 +0000354 for i in range(3):
Chui Tey5d2af632002-05-26 13:36:41 +0000355 time.sleep(i)
356 try:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000357 self.rpcclt = MyRPCClient(addr)
Chui Tey5d2af632002-05-26 13:36:41 +0000358 break
359 except socket.error, err:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000360 pass
Chui Tey5d2af632002-05-26 13:36:41 +0000361 else:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000362 self.display_port_binding_error()
363 return None
Kurt B. Kaiserb4179362002-07-26 00:06:42 +0000364 # Accept the connection from the Python execution server
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000365 self.rpcclt.listening_sock.settimeout(10)
366 try:
367 self.rpcclt.accept()
368 except socket.timeout, err:
369 self.display_no_subprocess_error()
370 return None
Kurt B. Kaiser969de452002-06-12 03:28:57 +0000371 self.rpcclt.register("stdin", self.tkconsole)
372 self.rpcclt.register("stdout", self.tkconsole.stdout)
373 self.rpcclt.register("stderr", self.tkconsole.stderr)
Chui Tey5d2af632002-05-26 13:36:41 +0000374 self.rpcclt.register("flist", self.tkconsole.flist)
Kurt B. Kaiser8cd0def2003-01-31 05:06:43 +0000375 self.rpcclt.register("linecache", linecache)
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000376 self.rpcclt.register("interp", self)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000377 self.transfer_path()
Chui Tey5d2af632002-05-26 13:36:41 +0000378 self.poll_subprocess()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000379 return self.rpcclt
Chui Tey5d2af632002-05-26 13:36:41 +0000380
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000381 def restart_subprocess(self):
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000382 if self.restarting:
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000383 return self.rpcclt
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000384 self.restarting = True
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000385 # close only the subprocess debugger
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000386 debug = self.getdebugger()
387 if debug:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000388 try:
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000389 # Only close subprocess debugger, don't unregister gui_adap!
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000390 RemoteDebugger.close_subprocess_debugger(self.rpcclt)
391 except:
392 pass
393 # Kill subprocess, spawn a new one, accept connection.
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000394 self.rpcclt.close()
395 self.unix_terminate()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000396 console = self.tkconsole
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000397 was_executing = console.executing
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000398 console.executing = False
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000399 self.spawn_subprocess()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000400 try:
401 self.rpcclt.accept()
402 except socket.timeout, err:
403 self.display_no_subprocess_error()
404 return None
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000405 self.transfer_path()
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000406 # annotate restart in shell window and mark it
Kurt B. Kaiser4cc5ef52003-01-22 00:23:23 +0000407 console.text.delete("iomark", "end-1c")
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000408 if was_executing:
409 console.write('\n')
410 console.showprompt()
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000411 halfbar = ((int(console.width) - 16) // 2) * '='
412 console.write(halfbar + ' RESTART ' + halfbar)
413 console.text.mark_set("restart", "end-1c")
414 console.text.mark_gravity("restart", "left")
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000415 console.showprompt()
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000416 # restart subprocess debugger
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000417 if debug:
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000418 # Restarted debugger connects to current instance of debug GUI
Kurt B. Kaiser63857a42002-09-05 02:31:20 +0000419 gui = RemoteDebugger.restart_subprocess_debugger(self.rpcclt)
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000420 # reload remote debugger breakpoints for all PyShellEditWindows
421 debug.load_breakpoints()
Kurt B. Kaiser6f805942003-05-24 21:12:46 +0000422 self.restarting = False
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000423 return self.rpcclt
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000424
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000425 def __request_interrupt(self):
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000426 self.rpcclt.remotecall("exec", "interrupt_the_server", (), {})
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000427
428 def interrupt_subprocess(self):
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000429 threading.Thread(target=self.__request_interrupt).start()
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000430
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000431 def kill_subprocess(self):
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000432 try:
433 self.rpcclt.close()
434 except AttributeError: # no socket
435 pass
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000436 self.unix_terminate()
437 self.tkconsole.executing = False
438 self.rpcclt = None
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000439
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000440 def unix_terminate(self):
441 "UNIX: make sure subprocess is terminated and collect status"
442 if hasattr(os, 'kill'):
443 try:
444 os.kill(self.rpcpid, SIGTERM)
445 except OSError:
446 # process already terminated:
447 return
448 else:
449 try:
450 os.waitpid(self.rpcpid, 0)
451 except OSError:
452 return
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000453
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000454 def transfer_path(self):
455 self.runcommand("""if 1:
456 import sys as _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +0000457 _sys.path = %r
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000458 del _sys
Kurt B. Kaiserb2487332003-03-04 04:03:45 +0000459 _msg = 'Use File/Exit or your end-of-file key to quit IDLE'
460 __builtins__.quit = __builtins__.exit = _msg
461 del _msg
Walter Dörwald70a6b492004-02-12 17:35:32 +0000462 \n""" % (sys.path,))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000463
Chui Tey5d2af632002-05-26 13:36:41 +0000464 active_seq = None
465
466 def poll_subprocess(self):
467 clt = self.rpcclt
468 if clt is None:
469 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000470 try:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000471 response = clt.pollresponse(self.active_seq, wait=0.05)
472 except (EOFError, IOError, KeyboardInterrupt):
473 # lost connection or subprocess terminated itself, restart
474 # [the KBI is from rpc.SocketIO.handle_EOF()]
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000475 if self.tkconsole.closing:
476 return
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000477 response = None
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000478 self.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000479 if response:
480 self.tkconsole.resetoutput()
481 self.active_seq = None
482 how, what = response
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000483 console = self.tkconsole.console
Chui Tey5d2af632002-05-26 13:36:41 +0000484 if how == "OK":
485 if what is not None:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000486 print >>console, repr(what)
Chui Tey5d2af632002-05-26 13:36:41 +0000487 elif how == "EXCEPTION":
Chui Tey5d2af632002-05-26 13:36:41 +0000488 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
489 self.remote_stack_viewer()
490 elif how == "ERROR":
Kurt B. Kaiser0930c432002-12-06 21:45:24 +0000491 errmsg = "PyShell.ModifiedInterpreter: Subprocess ERROR:\n"
492 print >>sys.__stderr__, errmsg, what
Kurt B. Kaiserbc286132003-01-25 21:33:40 +0000493 print >>console, errmsg, what
494 # we received a response to the currently active seq number:
Chui Tey5d2af632002-05-26 13:36:41 +0000495 self.tkconsole.endexecuting()
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000496 # Reschedule myself
497 if not self.tkconsole.closing:
498 self.tkconsole.text.after(self.tkconsole.pollinterval,
499 self.poll_subprocess)
Chui Tey5d2af632002-05-26 13:36:41 +0000500
Kurt B. Kaiser45186c42002-10-23 04:48:08 +0000501 debugger = None
502
503 def setdebugger(self, debugger):
504 self.debugger = debugger
505
506 def getdebugger(self):
507 return self.debugger
508
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000509 def open_remote_stack_viewer(self):
510 """Initiate the remote stack viewer from a separate thread.
511
512 This method is called from the subprocess, and by returning from this
513 method we allow the subprocess to unblock. After a bit the shell
514 requests the subprocess to open the remote stack viewer which returns a
515 static object looking at the last exceptiopn. It is queried through
516 the RPC mechanism.
517
518 """
519 self.tkconsole.text.after(300, self.remote_stack_viewer)
520 return
521
Chui Tey5d2af632002-05-26 13:36:41 +0000522 def remote_stack_viewer(self):
523 import RemoteObjectBrowser
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000524 oid = self.rpcclt.remotequeue("exec", "stackviewer", ("flist",), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000525 if oid is None:
526 self.tkconsole.root.bell()
527 return
528 item = RemoteObjectBrowser.StubObjectTreeItem(self.rpcclt, oid)
529 from TreeWidget import ScrolledCanvas, TreeNode
530 top = Toplevel(self.tkconsole.root)
Kurt B. Kaiser73360a32004-03-08 18:15:31 +0000531 theme = idleConf.GetOption('main','Theme','name')
532 background = idleConf.GetHighlight(theme, 'normal')['background']
533 sc = ScrolledCanvas(top, bg=background, highlightthickness=0)
Chui Tey5d2af632002-05-26 13:36:41 +0000534 sc.frame.pack(expand=1, fill="both")
535 node = TreeNode(sc.canvas, None, item)
536 node.expand()
537 # XXX Should GC the remote tree when closing the window
538
David Scherer7aced172000-08-15 01:13:23 +0000539 gid = 0
540
541 def execsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000542 "Like runsource() but assumes complete exec source"
David Scherer7aced172000-08-15 01:13:23 +0000543 filename = self.stuffsource(source)
544 self.execfile(filename, source)
545
546 def execfile(self, filename, source=None):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000547 "Execute an existing file"
David Scherer7aced172000-08-15 01:13:23 +0000548 if source is None:
549 source = open(filename, "r").read()
550 try:
551 code = compile(source, filename, "exec")
552 except (OverflowError, SyntaxError):
553 self.tkconsole.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000554 tkerr = self.tkconsole.stderr
555 print>>tkerr, '*** Error in script or command!\n'
556 print>>tkerr, 'Traceback (most recent call last):'
David Scherer7aced172000-08-15 01:13:23 +0000557 InteractiveInterpreter.showsyntaxerror(self, filename)
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000558 self.tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000559 else:
560 self.runcode(code)
561
562 def runsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000563 "Extend base class method: Stuff the source in the line cache first"
David Scherer7aced172000-08-15 01:13:23 +0000564 filename = self.stuffsource(source)
565 self.more = 0
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000566 self.save_warnings_filters = warnings.filters[:]
567 warnings.filterwarnings(action="error", category=SyntaxWarning)
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000568 if isinstance(source, types.UnicodeType):
569 import IOBinding
570 try:
571 source = source.encode(IOBinding.encoding)
572 except UnicodeError:
573 self.tkconsole.resetoutput()
574 self.write("Unsupported characters in input")
575 return
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000576 try:
577 return InteractiveInterpreter.runsource(self, source, filename)
578 finally:
579 if self.save_warnings_filters is not None:
580 warnings.filters[:] = self.save_warnings_filters
581 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000582
583 def stuffsource(self, source):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000584 "Stuff source in the filename cache"
David Scherer7aced172000-08-15 01:13:23 +0000585 filename = "<pyshell#%d>" % self.gid
586 self.gid = self.gid + 1
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000587 lines = source.split("\n")
David Scherer7aced172000-08-15 01:13:23 +0000588 linecache.cache[filename] = len(source)+1, 0, lines, filename
589 return filename
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +0000590
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000591 def prepend_syspath(self, filename):
592 "Prepend sys.path with file's directory if not already included"
593 self.runcommand("""if 1:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000594 _filename = %r
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000595 import sys as _sys
596 from os.path import dirname as _dirname
597 _dir = _dirname(_filename)
598 if not _dir in _sys.path:
599 _sys.path.insert(0, _dir)
600 del _filename, _sys, _dirname, _dir
Walter Dörwald70a6b492004-02-12 17:35:32 +0000601 \n""" % (filename,))
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +0000602
David Scherer7aced172000-08-15 01:13:23 +0000603 def showsyntaxerror(self, filename=None):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000604 """Extend base class method: Add Colorizing
605
606 Color the offending position instead of printing it and pointing at it
607 with a caret.
608
609 """
David Scherer7aced172000-08-15 01:13:23 +0000610 text = self.tkconsole.text
611 stuff = self.unpackerror()
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000612 if stuff:
613 msg, lineno, offset, line = stuff
614 if lineno == 1:
615 pos = "iomark + %d chars" % (offset-1)
616 else:
617 pos = "iomark linestart + %d lines + %d chars" % \
618 (lineno-1, offset-1)
619 text.tag_add("ERROR", pos)
620 text.see(pos)
621 char = text.get(pos)
622 if char and char in IDENTCHARS:
623 text.tag_add("ERROR", pos + " wordstart", pos)
624 self.tkconsole.resetoutput()
625 self.write("SyntaxError: %s\n" % str(msg))
626 else:
David Scherer7aced172000-08-15 01:13:23 +0000627 self.tkconsole.resetoutput()
628 InteractiveInterpreter.showsyntaxerror(self, filename)
Kurt B. Kaiser6e44cc22002-11-30 06:18:00 +0000629 self.tkconsole.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000630
631 def unpackerror(self):
632 type, value, tb = sys.exc_info()
633 ok = type is SyntaxError
634 if ok:
635 try:
636 msg, (dummy_filename, lineno, offset, line) = value
Kurt B. Kaiserbea57c62003-07-09 04:27:24 +0000637 if not offset:
638 offset = 0
David Scherer7aced172000-08-15 01:13:23 +0000639 except:
640 ok = 0
641 if ok:
642 return msg, lineno, offset, line
643 else:
644 return None
645
646 def showtraceback(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000647 "Extend base class method to reset output properly"
David Scherer7aced172000-08-15 01:13:23 +0000648 self.tkconsole.resetoutput()
649 self.checklinecache()
650 InteractiveInterpreter.showtraceback(self)
Chui Tey5d2af632002-05-26 13:36:41 +0000651 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
652 self.tkconsole.open_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +0000653
654 def checklinecache(self):
655 c = linecache.cache
656 for key in c.keys():
657 if key[:1] + key[-1:] != "<>":
658 del c[key]
659
Chui Tey5d2af632002-05-26 13:36:41 +0000660 def runcommand(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000661 "Run the code without invoking the debugger"
Chui Tey5d2af632002-05-26 13:36:41 +0000662 # The code better not raise an exception!
663 if self.tkconsole.executing:
Neal Norwitzf4c4f112002-11-30 18:49:10 +0000664 self.display_executing_dialog()
Chui Tey5d2af632002-05-26 13:36:41 +0000665 return 0
666 if self.rpcclt:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000667 self.rpcclt.remotequeue("exec", "runcode", (code,), {})
Chui Tey5d2af632002-05-26 13:36:41 +0000668 else:
669 exec code in self.locals
670 return 1
671
David Scherer7aced172000-08-15 01:13:23 +0000672 def runcode(self, code):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000673 "Override base class method"
Chui Tey5d2af632002-05-26 13:36:41 +0000674 if self.tkconsole.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000675 self.interp.restart_subprocess()
Chui Tey5d2af632002-05-26 13:36:41 +0000676 self.checklinecache()
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000677 if self.save_warnings_filters is not None:
678 warnings.filters[:] = self.save_warnings_filters
679 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000680 debugger = self.debugger
681 try:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000682 self.tkconsole.beginexecuting()
683 try:
684 if not debugger and self.rpcclt is not None:
685 self.active_seq = self.rpcclt.asyncqueue("exec", "runcode",
686 (code,), {})
687 elif debugger:
688 debugger.run(code, self.locals)
689 else:
690 exec code in self.locals
691 except SystemExit:
692 if tkMessageBox.askyesno(
693 "Exit?",
694 "Do you want to exit altogether?",
695 default="yes",
696 master=self.tkconsole.text):
697 raise
698 else:
699 self.showtraceback()
700 except:
David Scherer7aced172000-08-15 01:13:23 +0000701 self.showtraceback()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000702 finally:
703 if not use_subprocess:
704 self.tkconsole.endexecuting()
David Scherer7aced172000-08-15 01:13:23 +0000705
706 def write(self, s):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000707 "Override base class method"
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000708 self.tkconsole.stderr.write(s)
David Scherer7aced172000-08-15 01:13:23 +0000709
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000710 def display_port_binding_error(self):
711 tkMessageBox.showerror(
712 "Port Binding Error",
713 "IDLE can't bind TCP/IP port 8833, which is necessary to "
714 "communicate with its Python execution server. Either "
715 "no networking is installed on this computer or another "
716 "process (another IDLE?) is using the port. Run IDLE with the -n "
717 "command line switch to start without a subprocess and refer to "
718 "Help/IDLE Help 'Running without a subprocess' for further "
719 "details.",
720 master=self.tkconsole.text)
721
722 def display_no_subprocess_error(self):
723 tkMessageBox.showerror(
724 "Subprocess Startup Error",
725 "IDLE's subprocess didn't make connection. Either IDLE can't "
726 "start a subprocess or personal firewall software is blocking "
727 "the connection.",
728 master=self.tkconsole.text)
729
730 def display_executing_dialog(self):
731 tkMessageBox.showerror(
732 "Already executing",
733 "The Python Shell window is already executing a command; "
734 "please wait until it is finished.",
735 master=self.tkconsole.text)
736
737
David Scherer7aced172000-08-15 01:13:23 +0000738class PyShell(OutputWindow):
739
740 shell_title = "Python Shell"
741
742 # Override classes
743 ColorDelegator = ModifiedColorDelegator
744 UndoDelegator = ModifiedUndoDelegator
745
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +0000746 # Override menus
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000747 menu_specs = [
748 ("file", "_File"),
749 ("edit", "_Edit"),
Kurt B. Kaiser4cc5ef52003-01-22 00:23:23 +0000750 ("debug", "_Debug"),
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000751 ("options", "_Options"),
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +0000752 ("windows", "_Windows"),
753 ("help", "_Help"),
754 ]
David Scherer7aced172000-08-15 01:13:23 +0000755
756 # New classes
757 from IdleHistory import History
758
759 def __init__(self, flist=None):
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000760 if use_subprocess:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000761 ms = self.menu_specs
762 if ms[2][0] != "shell":
763 ms.insert(2, ("shell", "_Shell"))
David Scherer7aced172000-08-15 01:13:23 +0000764 self.interp = ModifiedInterpreter(self)
765 if flist is None:
766 root = Tk()
767 fixwordbreaks(root)
768 root.withdraw()
769 flist = PyShellFileList(root)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000770 #
David Scherer7aced172000-08-15 01:13:23 +0000771 OutputWindow.__init__(self, flist, None, None)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000772 #
David Scherer7aced172000-08-15 01:13:23 +0000773 import __builtin__
774 __builtin__.quit = __builtin__.exit = "To exit, type Ctrl-D."
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000775 #
Kurt B. Kaiseree7afca2002-09-14 02:50:56 +0000776 self.config(usetabs=1, indentwidth=8, context_use_ps1=1)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000777 #
David Scherer7aced172000-08-15 01:13:23 +0000778 text = self.text
779 text.configure(wrap="char")
780 text.bind("<<newline-and-indent>>", self.enter_callback)
781 text.bind("<<plain-newline-and-indent>>", self.linefeed_callback)
782 text.bind("<<interrupt-execution>>", self.cancel_callback)
783 text.bind("<<beginning-of-line>>", self.home_callback)
784 text.bind("<<end-of-file>>", self.eof_callback)
785 text.bind("<<open-stack-viewer>>", self.open_stack_viewer)
Kurt B. Kaiser57bfe5d2003-05-10 00:09:52 +0000786 text.bind("<<toggle-debugger>>", self.toggle_debugger)
David Scherer7aced172000-08-15 01:13:23 +0000787 text.bind("<<open-python-shell>>", self.flist.open_shell)
788 text.bind("<<toggle-jit-stack-viewer>>", self.toggle_jit_stack_viewer)
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000789 if use_subprocess:
790 text.bind("<<view-restart>>", self.view_restart_mark)
791 text.bind("<<restart-shell>>", self.restart_shell)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000792 #
David Scherer7aced172000-08-15 01:13:23 +0000793 self.save_stdout = sys.stdout
794 self.save_stderr = sys.stderr
795 self.save_stdin = sys.stdin
Martin v. Löwisbcc651a2003-06-22 07:52:56 +0000796 import IOBinding
797 self.stdout = PseudoFile(self, "stdout", IOBinding.encoding)
798 self.stderr = PseudoFile(self, "stderr", IOBinding.encoding)
799 self.console = PseudoFile(self, "console", IOBinding.encoding)
Chui Tey5d2af632002-05-26 13:36:41 +0000800 if not use_subprocess:
801 sys.stdout = self.stdout
802 sys.stderr = self.stderr
803 sys.stdin = self
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000804 #
David Scherer7aced172000-08-15 01:13:23 +0000805 self.history = self.History(self.text)
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000806 #
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000807 self.pollinterval = 50 # millisec
Chui Tey5d2af632002-05-26 13:36:41 +0000808
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000809 reading = False
810 executing = False
811 canceled = False
812 endoffile = False
813 closing = False
David Scherer7aced172000-08-15 01:13:23 +0000814
815 def toggle_debugger(self, event=None):
816 if self.executing:
817 tkMessageBox.showerror("Don't debug now",
818 "You can only toggle the debugger when idle",
819 master=self.text)
820 self.set_debugger_indicator()
821 return "break"
822 else:
823 db = self.interp.getdebugger()
824 if db:
825 self.close_debugger()
826 else:
827 self.open_debugger()
828
829 def set_debugger_indicator(self):
830 db = self.interp.getdebugger()
831 self.setvar("<<toggle-debugger>>", not not db)
832
Kurt B. Kaiser1061e722003-01-04 01:43:53 +0000833 def toggle_jit_stack_viewer(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +0000834 pass # All we need is the variable
835
836 def close_debugger(self):
837 db = self.interp.getdebugger()
838 if db:
839 self.interp.setdebugger(None)
840 db.close()
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000841 if self.interp.rpcclt:
842 RemoteDebugger.close_remote_debugger(self.interp.rpcclt)
David Scherer7aced172000-08-15 01:13:23 +0000843 self.resetoutput()
844 self.console.write("[DEBUG OFF]\n")
845 sys.ps1 = ">>> "
846 self.showprompt()
847 self.set_debugger_indicator()
848
849 def open_debugger(self):
Chui Tey5d2af632002-05-26 13:36:41 +0000850 if self.interp.rpcclt:
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000851 dbg_gui = RemoteDebugger.start_remote_debugger(self.interp.rpcclt,
852 self)
853 else:
854 dbg_gui = Debugger.Debugger(self)
855 self.interp.setdebugger(dbg_gui)
856 dbg_gui.load_breakpoints()
Chui Tey5d2af632002-05-26 13:36:41 +0000857 sys.ps1 = "[DEBUG ON]\n>>> "
858 self.showprompt()
859 self.set_debugger_indicator()
860
David Scherer7aced172000-08-15 01:13:23 +0000861 def beginexecuting(self):
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000862 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +0000863 self.resetoutput()
864 self.executing = 1
David Scherer7aced172000-08-15 01:13:23 +0000865
866 def endexecuting(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000867 "Helper for ModifiedInterpreter"
David Scherer7aced172000-08-15 01:13:23 +0000868 self.executing = 0
869 self.canceled = 0
Chui Tey5d2af632002-05-26 13:36:41 +0000870 self.showprompt()
David Scherer7aced172000-08-15 01:13:23 +0000871
872 def close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000873 "Extend EditorWindow.close()"
David Scherer7aced172000-08-15 01:13:23 +0000874 if self.executing:
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000875 response = tkMessageBox.askokcancel(
David Scherer7aced172000-08-15 01:13:23 +0000876 "Kill?",
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000877 "The program is still running!\n Do you want to kill it?",
David Scherer7aced172000-08-15 01:13:23 +0000878 default="ok",
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000879 parent=self.text)
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000880 if response == False:
David Scherer7aced172000-08-15 01:13:23 +0000881 return "cancel"
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000882 self.closing = True
883 # Wait for poll_subprocess() rescheduling to stop
884 self.text.after(2 * self.pollinterval, self.close2)
Kurt B. Kaiser88957d82003-05-19 23:11:51 +0000885
886 def close2(self):
887 return EditorWindow.close(self)
David Scherer7aced172000-08-15 01:13:23 +0000888
889 def _close(self):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000890 "Extend EditorWindow._close(), shut down debugger and execution server"
David Scherer7aced172000-08-15 01:13:23 +0000891 self.close_debugger()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000892 if use_subprocess:
893 self.interp.kill_subprocess()
David Scherer7aced172000-08-15 01:13:23 +0000894 # Restore std streams
895 sys.stdout = self.save_stdout
896 sys.stderr = self.save_stderr
897 sys.stdin = self.save_stdin
898 # Break cycles
899 self.interp = None
900 self.console = None
David Scherer7aced172000-08-15 01:13:23 +0000901 self.flist.pyshell = None
902 self.history = None
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000903 EditorWindow._close(self)
David Scherer7aced172000-08-15 01:13:23 +0000904
905 def ispythonsource(self, filename):
Kurt B. Kaiser83118c62002-06-24 17:03:37 +0000906 "Override EditorWindow method: never remove the colorizer"
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000907 return True
David Scherer7aced172000-08-15 01:13:23 +0000908
909 def short_title(self):
910 return self.shell_title
911
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000912 COPYRIGHT = \
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +0000913 'Type "copyright", "credits" or "license()" for more information.'
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000914
Kurt B. Kaiser220fecf2003-07-27 03:24:19 +0000915 firewallmessage = """
916 ****************************************************************
917 Personal firewall software may warn about the connection IDLE
918 makes to its subprocess using this computer's internal loopback
919 interface. This connection is not visible on any external
920 interface and no data is sent to or received from the Internet.
921 ****************************************************************
922 """
923
David Scherer7aced172000-08-15 01:13:23 +0000924 def begin(self):
925 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000926 if use_subprocess:
927 nosub = ''
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000928 client = self.interp.start_subprocess()
929 if not client:
930 self.close()
Kurt B. Kaiser76637292004-01-21 22:10:01 +0000931 return False
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000932 else:
933 nosub = "==== No Subprocess ===="
Kurt B. Kaiser220fecf2003-07-27 03:24:19 +0000934 self.write("Python %s on %s\n%s\n%s\nIDLE %s %s\n" %
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000935 (sys.version, sys.platform, self.COPYRIGHT,
Kurt B. Kaiser220fecf2003-07-27 03:24:19 +0000936 self.firewallmessage, idlever.IDLE_VERSION, nosub))
David Scherer7aced172000-08-15 01:13:23 +0000937 self.showprompt()
938 import Tkinter
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000939 Tkinter._default_root = None # 03Jan04 KBK What's this?
Kurt B. Kaiser76637292004-01-21 22:10:01 +0000940 return True
David Scherer7aced172000-08-15 01:13:23 +0000941
942 def readline(self):
943 save = self.reading
944 try:
945 self.reading = 1
946 self.top.mainloop()
947 finally:
948 self.reading = save
949 line = self.text.get("iomark", "end-1c")
Martin v. Löwisbcc651a2003-06-22 07:52:56 +0000950 if isinstance(line, unicode):
951 import IOBinding
952 try:
953 line = line.encode(IOBinding.encoding)
954 except UnicodeError:
955 pass
David Scherer7aced172000-08-15 01:13:23 +0000956 self.resetoutput()
957 if self.canceled:
958 self.canceled = 0
959 raise KeyboardInterrupt
960 if self.endoffile:
961 self.endoffile = 0
962 return ""
963 return line
964
965 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +0000966 return True
David Scherer7aced172000-08-15 01:13:23 +0000967
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000968 def cancel_callback(self, event=None):
David Scherer7aced172000-08-15 01:13:23 +0000969 try:
970 if self.text.compare("sel.first", "!=", "sel.last"):
971 return # Active selection -- always use default binding
972 except:
973 pass
974 if not (self.executing or self.reading):
975 self.resetoutput()
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +0000976 self.interp.write("KeyboardInterrupt\n")
David Scherer7aced172000-08-15 01:13:23 +0000977 self.showprompt()
978 return "break"
979 self.endoffile = 0
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000980 self.canceled = 1
David Scherer7aced172000-08-15 01:13:23 +0000981 if self.reading:
982 self.top.quit()
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000983 elif (self.executing and self.interp.rpcclt):
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000984 if self.interp.getdebugger():
985 self.interp.restart_subprocess()
986 else:
987 self.interp.interrupt_subprocess()
David Scherer7aced172000-08-15 01:13:23 +0000988 return "break"
989
990 def eof_callback(self, event):
991 if self.executing and not self.reading:
992 return # Let the default binding (delete next char) take over
993 if not (self.text.compare("iomark", "==", "insert") and
994 self.text.compare("insert", "==", "end-1c")):
995 return # Let the default binding (delete next char) take over
996 if not self.executing:
David Scherer7aced172000-08-15 01:13:23 +0000997 self.resetoutput()
998 self.close()
999 else:
1000 self.canceled = 0
1001 self.endoffile = 1
1002 self.top.quit()
1003 return "break"
1004
1005 def home_callback(self, event):
1006 if event.state != 0 and event.keysym == "Home":
1007 return # <Modifier-Home>; fall back to class binding
1008 if self.text.compare("iomark", "<=", "insert") and \
1009 self.text.compare("insert linestart", "<=", "iomark"):
1010 self.text.mark_set("insert", "iomark")
1011 self.text.tag_remove("sel", "1.0", "end")
1012 self.text.see("insert")
1013 return "break"
1014
1015 def linefeed_callback(self, event):
1016 # Insert a linefeed without entering anything (still autoindented)
1017 if self.reading:
1018 self.text.insert("insert", "\n")
1019 self.text.see("insert")
1020 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001021 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001022 return "break"
1023
1024 def enter_callback(self, event):
1025 if self.executing and not self.reading:
1026 return # Let the default binding (insert '\n') take over
1027 # If some text is selected, recall the selection
1028 # (but only if this before the I/O mark)
1029 try:
1030 sel = self.text.get("sel.first", "sel.last")
1031 if sel:
1032 if self.text.compare("sel.last", "<=", "iomark"):
1033 self.recall(sel)
1034 return "break"
1035 except:
1036 pass
1037 # If we're strictly before the line containing iomark, recall
1038 # the current line, less a leading prompt, less leading or
1039 # trailing whitespace
1040 if self.text.compare("insert", "<", "iomark linestart"):
1041 # Check if there's a relevant stdin range -- if so, use it
1042 prev = self.text.tag_prevrange("stdin", "insert")
1043 if prev and self.text.compare("insert", "<", prev[1]):
1044 self.recall(self.text.get(prev[0], prev[1]))
1045 return "break"
1046 next = self.text.tag_nextrange("stdin", "insert")
1047 if next and self.text.compare("insert lineend", ">=", next[0]):
1048 self.recall(self.text.get(next[0], next[1]))
1049 return "break"
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001050 # No stdin mark -- just get the current line, less any prompt
1051 line = self.text.get("insert linestart", "insert lineend")
1052 last_line_of_prompt = sys.ps1.split('\n')[-1]
1053 if line.startswith(last_line_of_prompt):
1054 line = line[len(last_line_of_prompt):]
1055 self.recall(line)
David Scherer7aced172000-08-15 01:13:23 +00001056 return "break"
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001057 # If we're between the beginning of the line and the iomark, i.e.
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001058 # in the prompt area, move to the end of the prompt
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001059 if self.text.compare("insert", "<", "iomark"):
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001060 self.text.mark_set("insert", "iomark")
David Scherer7aced172000-08-15 01:13:23 +00001061 # If we're in the current input and there's only whitespace
1062 # beyond the cursor, erase that whitespace first
1063 s = self.text.get("insert", "end-1c")
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001064 if s and not s.strip():
David Scherer7aced172000-08-15 01:13:23 +00001065 self.text.delete("insert", "end-1c")
1066 # If we're in the current input before its last line,
1067 # insert a newline right at the insert point
1068 if self.text.compare("insert", "<", "end-1c linestart"):
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001069 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001070 return "break"
1071 # We're in the last line; append a newline and submit it
1072 self.text.mark_set("insert", "end-1c")
1073 if self.reading:
1074 self.text.insert("insert", "\n")
1075 self.text.see("insert")
1076 else:
Kurt B. Kaiser822a77f2002-12-16 02:07:11 +00001077 self.newline_and_indent_event(event)
David Scherer7aced172000-08-15 01:13:23 +00001078 self.text.tag_add("stdin", "iomark", "end-1c")
1079 self.text.update_idletasks()
1080 if self.reading:
1081 self.top.quit() # Break out of recursive mainloop() in raw_input()
1082 else:
1083 self.runit()
1084 return "break"
1085
1086 def recall(self, s):
1087 if self.history:
1088 self.history.recall(s)
1089
1090 def runit(self):
1091 line = self.text.get("iomark", "end-1c")
1092 # Strip off last newline and surrounding whitespace.
1093 # (To allow you to hit return twice to end a statement.)
1094 i = len(line)
1095 while i > 0 and line[i-1] in " \t":
1096 i = i-1
1097 if i > 0 and line[i-1] == "\n":
1098 i = i-1
1099 while i > 0 and line[i-1] in " \t":
1100 i = i-1
1101 line = line[:i]
1102 more = self.interp.runsource(line)
David Scherer7aced172000-08-15 01:13:23 +00001103
David Scherer7aced172000-08-15 01:13:23 +00001104 def open_stack_viewer(self, event=None):
Chui Tey5d2af632002-05-26 13:36:41 +00001105 if self.interp.rpcclt:
1106 return self.interp.remote_stack_viewer()
David Scherer7aced172000-08-15 01:13:23 +00001107 try:
1108 sys.last_traceback
1109 except:
1110 tkMessageBox.showerror("No stack trace",
1111 "There is no stack trace yet.\n"
1112 "(sys.last_traceback is not defined)",
1113 master=self.text)
1114 return
1115 from StackViewer import StackBrowser
1116 sv = StackBrowser(self.root, self.flist)
1117
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001118 def view_restart_mark(self, event=None):
1119 self.text.see("iomark")
1120 self.text.see("restart")
1121
1122 def restart_shell(self, event=None):
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +00001123 self.interp.restart_subprocess()
Kurt B. Kaiser1061e722003-01-04 01:43:53 +00001124
David Scherer7aced172000-08-15 01:13:23 +00001125 def showprompt(self):
1126 self.resetoutput()
1127 try:
1128 s = str(sys.ps1)
1129 except:
1130 s = ""
1131 self.console.write(s)
1132 self.text.mark_set("insert", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001133 self.set_line_and_column()
Kurt B. Kaiserdc1e7092002-07-11 04:33:41 +00001134 self.io.reset_undo()
David Scherer7aced172000-08-15 01:13:23 +00001135
1136 def resetoutput(self):
1137 source = self.text.get("iomark", "end-1c")
1138 if self.history:
1139 self.history.history_store(source)
1140 if self.text.get("end-2c") != "\n":
1141 self.text.insert("end-1c", "\n")
1142 self.text.mark_set("iomark", "end-1c")
Chui Tey5d2af632002-05-26 13:36:41 +00001143 self.set_line_and_column()
David Scherer7aced172000-08-15 01:13:23 +00001144 sys.stdout.softspace = 0
1145
1146 def write(self, s, tags=()):
Kurt B. Kaiser003091c2003-02-17 18:57:16 +00001147 try:
1148 self.text.mark_gravity("iomark", "right")
1149 OutputWindow.write(self, s, tags, "iomark")
1150 self.text.mark_gravity("iomark", "left")
1151 except:
1152 pass
David Scherer7aced172000-08-15 01:13:23 +00001153 if self.canceled:
1154 self.canceled = 0
Kurt B. Kaiser7f38ec02003-05-15 03:19:42 +00001155 if not use_subprocess:
1156 raise KeyboardInterrupt
David Scherer7aced172000-08-15 01:13:23 +00001157
1158class PseudoFile:
1159
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001160 def __init__(self, shell, tags, encoding=None):
David Scherer7aced172000-08-15 01:13:23 +00001161 self.shell = shell
1162 self.tags = tags
Chui Tey5d2af632002-05-26 13:36:41 +00001163 self.softspace = 0
Martin v. Löwisbcc651a2003-06-22 07:52:56 +00001164 self.encoding = encoding
David Scherer7aced172000-08-15 01:13:23 +00001165
1166 def write(self, s):
1167 self.shell.write(s, self.tags)
1168
1169 def writelines(self, l):
1170 map(self.write, l)
1171
1172 def flush(self):
1173 pass
1174
1175 def isatty(self):
Kurt B. Kaiser837d15c2002-09-18 02:29:59 +00001176 return True
David Scherer7aced172000-08-15 01:13:23 +00001177
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001178
David Scherer7aced172000-08-15 01:13:23 +00001179usage_msg = """\
David Scherer7aced172000-08-15 01:13:23 +00001180
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001181USAGE: idle [-deins] [-t title] [file]*
1182 idle [-dns] [-t title] (-c cmd | -r file) [arg]*
1183 idle [-dns] [-t title] - [arg]*
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001184
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001185 -h print this help message and exit
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001186 -n run IDLE without a subprocess (see Help/IDLE Help for details)
David Scherer7aced172000-08-15 01:13:23 +00001187
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001188The following options will override the IDLE 'settings' configuration:
Kurt B. Kaiser96d88422001-07-17 04:59:01 +00001189
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001190 -e open an edit window
1191 -i open a shell window
1192
1193The following options imply -i and will open a shell:
1194
1195 -c cmd run the command in a shell, or
1196 -r file run script from file
1197
1198 -d enable the debugger
1199 -s run $IDLESTARTUP or $PYTHONSTARTUP before anything else
1200 -t title set title of shell window
1201
1202A default edit window will be bypassed when -c, -r, or - are used.
1203
1204[arg]* are passed to the command (-c) or script (-r) in sys.argv[1:].
1205
1206Examples:
1207
1208idle
1209 Open an edit window or shell depending on IDLE's configuration.
1210
1211idle foo.py foobar.py
1212 Edit the files, also open a shell if configured to start with shell.
1213
1214idle -est "Baz" foo.py
1215 Run $IDLESTARTUP or $PYTHONSTARTUP, edit foo.py, and open a shell
1216 window with the title "Baz".
1217
1218idle -c "import sys; print sys.argv" "foo"
1219 Open a shell window and run the command, passing "-c" in sys.argv[0]
1220 and "foo" in sys.argv[1].
1221
1222idle -d -s -r foo.py "Hello World"
1223 Open a shell window, run a startup script, enable the debugger, and
1224 run foo.py, passing "foo.py" in sys.argv[0] and "Hello World" in
1225 sys.argv[1].
1226
1227echo "import sys; print sys.argv" | idle - "foobar"
1228 Open a shell window, run the script piped in, passing '' in sys.argv[0]
1229 and "foobar" in sys.argv[1].
David Scherer7aced172000-08-15 01:13:23 +00001230"""
1231
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001232def main():
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001233 global flist, root, use_subprocess
David Scherer7aced172000-08-15 01:13:23 +00001234
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001235 use_subprocess = True
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001236 enable_shell = False
1237 enable_edit = False
1238 debug = False
1239 cmd = None
1240 script = None
1241 startup = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001242 try:
Kurt B. Kaiser4ada7ad2002-12-29 22:03:38 +00001243 sys.ps1
1244 except AttributeError:
1245 sys.ps1 = '>>> '
1246 try:
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001247 opts, args = getopt.getopt(sys.argv[1:], "c:deihnr:st:")
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001248 except getopt.error, msg:
1249 sys.stderr.write("Error: %s\n" % str(msg))
1250 sys.stderr.write(usage_msg)
1251 sys.exit(2)
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001252 for o, a in opts:
1253 if o == '-c':
1254 cmd = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001255 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001256 if o == '-d':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001257 debug = True
1258 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001259 if o == '-e':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001260 enable_edit = True
1261 if o == '-h':
1262 sys.stdout.write(usage_msg)
1263 sys.exit()
1264 if o == '-i':
1265 enable_shell = True
Kurt B. Kaiser8f570a72003-05-15 18:52:51 +00001266 if o == '-n':
1267 use_subprocess = False
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001268 if o == '-r':
1269 script = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001270 if os.path.isfile(script):
1271 pass
1272 else:
1273 print "No script file: ", script
1274 sys.exit()
1275 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001276 if o == '-s':
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001277 startup = True
1278 enable_shell = True
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001279 if o == '-t':
1280 PyShell.shell_title = a
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001281 enable_shell = True
1282 if args and args[0] == '-':
1283 cmd = sys.stdin.read()
1284 enable_shell = True
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001285 # process sys.argv and sys.path:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001286 for i in range(len(sys.path)):
1287 sys.path[i] = os.path.abspath(sys.path[i])
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001288 if args and args[0] == '-':
1289 sys.argv = [''] + args[1:]
1290 elif cmd:
1291 sys.argv = ['-c'] + args
1292 elif script:
1293 sys.argv = [script] + args
1294 elif args:
1295 enable_edit = True
1296 pathx = []
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001297 for filename in args:
1298 pathx.append(os.path.dirname(filename))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001299 for dir in pathx:
1300 dir = os.path.abspath(dir)
1301 if not dir in sys.path:
1302 sys.path.insert(0, dir)
Kurt B. Kaiserff002b92002-12-21 21:39:11 +00001303 else:
1304 dir = os.getcwd()
1305 if not dir in sys.path:
1306 sys.path.insert(0, dir)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001307 # check the IDLE settings configuration (but command line overrides)
1308 edit_start = idleConf.GetOption('main', 'General',
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001309 'editor-on-startup', type='bool')
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001310 enable_edit = enable_edit or edit_start
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +00001311 enable_shell = enable_shell or not edit_start
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001312 # start editor and/or shell windows:
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001313 root = Tk(className="Idle")
1314 fixwordbreaks(root)
1315 root.withdraw()
1316 flist = PyShellFileList(root)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001317 if enable_edit:
1318 if not (cmd or script):
1319 for filename in args:
1320 flist.open(filename)
1321 if not args:
1322 flist.new()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001323 if enable_shell:
1324 if not flist.open_shell():
1325 return # couldn't open shell
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001326 shell = flist.pyshell
1327 # handle remaining options:
1328 if debug:
1329 shell.open_debugger()
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001330 if startup:
1331 filename = os.environ.get("IDLESTARTUP") or \
1332 os.environ.get("PYTHONSTARTUP")
1333 if filename and os.path.isfile(filename):
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001334 shell.interp.execfile(filename)
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +00001335 if shell and cmd or script:
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001336 shell.interp.runcommand("""if 1:
1337 import sys as _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001338 _sys.argv = %r
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001339 del _sys
Walter Dörwald70a6b492004-02-12 17:35:32 +00001340 \n""" % (sys.argv,))
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001341 if cmd:
1342 shell.interp.execsource(cmd)
1343 elif script:
Kurt B. Kaiser11659ad2003-05-15 23:23:21 +00001344 shell.interp.prepend_syspath(script)
Kurt B. Kaiserf06eed02002-12-11 04:42:04 +00001345 shell.interp.execfile(script)
Kurt B. Kaiser969de452002-06-12 03:28:57 +00001346 root.mainloop()
1347 root.destroy()
1348
David Scherer7aced172000-08-15 01:13:23 +00001349if __name__ == "__main__":
Kurt B. Kaiser9e8b8282003-06-15 17:38:45 +00001350 sys.modules['PyShell'] = sys.modules['__main__']
David Scherer7aced172000-08-15 01:13:23 +00001351 main()