summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
authorKurt B. Kaiser <kbk@shore.net>2003-05-15 03:19:42 (GMT)
committerKurt B. Kaiser <kbk@shore.net>2003-05-15 03:19:42 (GMT)
commit7f38ec0849fd2b19e660350c59d42b8b5cfae2d1 (patch)
tree243051301d3e14045e8b118b83ab7fa7d8719e05 /Lib
parentf655dff80782cd6bf59d64985299bd07546cb98b (diff)
downloadcpython-7f38ec0849fd2b19e660350c59d42b8b5cfae2d1.zip
cpython-7f38ec0849fd2b19e660350c59d42b8b5cfae2d1.tar.gz
cpython-7f38ec0849fd2b19e660350c59d42b8b5cfae2d1.tar.bz2
1. Restore the capability to run and debug without a subprocess.
2. Add an indicator to the shell startup notice when running w/o subprocess. 3. Improve exception reporting when running a command or script from the command line. 4. Clarify the fact that breakpoints set or cleared after a file is saved will revert to the saved state if the file is closed without re-saving. 5. If user tries to exit or restart when user code is running, interrupt the user code. This helps to eliminate occasional hanging subprocesses on Windows (except for Freddy :). M NEWS.txt M PyShell.py M ScriptBinding.py
Diffstat (limited to 'Lib')
-rw-r--r--Lib/idlelib/NEWS.txt16
-rw-r--r--Lib/idlelib/PyShell.py119
-rw-r--r--Lib/idlelib/ScriptBinding.py17
3 files changed, 98 insertions, 54 deletions
diff --git a/Lib/idlelib/NEWS.txt b/Lib/idlelib/NEWS.txt
index ba0307e..d24c34b9 100644
--- a/Lib/idlelib/NEWS.txt
+++ b/Lib/idlelib/NEWS.txt
@@ -7,6 +7,22 @@ What's New in IDLEfork 0.9b1?
*Release date: XX-XXX-2003*
+- Interrupt the subprocess if it is running when the user attempts to
+ restart the shell, run a module, or exit.
+
+- Improved exception reporting when running commands or scripts from the
+ command line.
+
+- Added a comment to the shell startup header to indicate when IDLE is not
+ using the subprocess. (For now, set PyShell.use_subprocess to False to run
+ in this mode.)
+
+- Restore the ability to run without the subprocess. This can be important for
+ some platforms or configurations. (Running without the subprocess allows the
+ debugger to trace through parts of IDLE itself, which may or may not be
+ desirable, depending on your point of view. In addition, the traditional
+ reload/import tricks must be use if user source code is changed.)
+
- Improve the error message a user gets when saving a file with non-ASCII
characters and no source encoding is specified. Done by adding a dialog
'EncodingMessage', which contains the line to add in a fixed-font entry
diff --git a/Lib/idlelib/PyShell.py b/Lib/idlelib/PyShell.py
index 6e3a43a..f3312a8 100644
--- a/Lib/idlelib/PyShell.py
+++ b/Lib/idlelib/PyShell.py
@@ -31,6 +31,7 @@ from configHandler import idleConf
import idlever
import rpc
+import Debugger
import RemoteDebugger
IDENTCHARS = string.ascii_letters + string.digits + "_"
@@ -160,9 +161,10 @@ class PyShellEditorWindow(EditorWindow):
# a temporary file save feature the save breaks functionality
# needs to be re-verified, since the breaks at the time the
# temp file is created may differ from the breaks at the last
- # permanent save of the file. A break introduced after a save
- # will be effective, but not persistent. This is necessary to
- # keep the saved breaks synched with the saved file.
+ # permanent save of the file. Currently, a break introduced
+ # after a save will be effective, but not persistent.
+ # This is necessary to keep the saved breaks synched with the
+ # saved file.
#
# Breakpoints are set as tagged ranges in the text. Certain
# kinds of edits cause these ranges to be deleted: Inserting
@@ -361,17 +363,18 @@ class ModifiedInterpreter(InteractiveInterpreter):
# Kill subprocess, spawn a new one, accept connection.
self.rpcclt.close()
self.unix_terminate()
- self.tkconsole.executing = False
+ console = self.tkconsole
+ console.executing = False
self.spawn_subprocess()
self.rpcclt.accept()
self.transfer_path()
# annotate restart in shell window and mark it
- console = self.tkconsole
console.text.delete("iomark", "end-1c")
halfbar = ((int(console.width) - 16) // 2) * '='
console.write(halfbar + ' RESTART ' + halfbar)
console.text.mark_set("restart", "end-1c")
console.text.mark_gravity("restart", "left")
+ console.showprompt()
# restart subprocess debugger
if debug:
# Restarted debugger connects to current instance of debug GUI
@@ -489,8 +492,9 @@ class ModifiedInterpreter(InteractiveInterpreter):
code = compile(source, filename, "exec")
except (OverflowError, SyntaxError):
self.tkconsole.resetoutput()
- console = self.tkconsole.console
- print >>console, 'Traceback (most recent call last):'
+ tkerr = self.tkconsole.stderr
+ print>>tkerr, '*** Error in script or command!\n'
+ print>>tkerr, 'Traceback (most recent call last):'
InteractiveInterpreter.showsyntaxerror(self, filename)
self.tkconsole.showprompt()
else:
@@ -608,30 +612,34 @@ class ModifiedInterpreter(InteractiveInterpreter):
warnings.filters[:] = self.save_warnings_filters
self.save_warnings_filters = None
debugger = self.debugger
- self.tkconsole.beginexecuting()
try:
- if not debugger and self.rpcclt is not None:
- self.active_seq = self.rpcclt.asyncqueue("exec", "runcode",
- (code,), {})
- elif debugger:
- debugger.run(code, self.locals)
- else:
- exec code in self.locals
- except SystemExit:
- if tkMessageBox.askyesno(
- "Exit?",
- "Do you want to exit altogether?",
- default="yes",
- master=self.tkconsole.text):
- raise
- else:
+ self.tkconsole.beginexecuting()
+ try:
+ if not debugger and self.rpcclt is not None:
+ self.active_seq = self.rpcclt.asyncqueue("exec", "runcode",
+ (code,), {})
+ elif debugger:
+ debugger.run(code, self.locals)
+ else:
+ exec code in self.locals
+ except SystemExit:
+ if tkMessageBox.askyesno(
+ "Exit?",
+ "Do you want to exit altogether?",
+ default="yes",
+ master=self.tkconsole.text):
+ raise
+ else:
+ self.showtraceback()
+ except:
self.showtraceback()
- except:
- self.showtraceback()
+ finally:
+ if not use_subprocess:
+ self.tkconsole.endexecuting()
def write(self, s):
"Override base class method"
- self.tkconsole.console.write(s)
+ self.tkconsole.stderr.write(s)
class PyShell(OutputWindow):
@@ -741,22 +749,13 @@ class PyShell(OutputWindow):
self.set_debugger_indicator()
def open_debugger(self):
- # XXX KBK 13Jun02 An RPC client always exists now? Open remote
- # debugger and return...dike the rest of this fcn and combine
- # with open_remote_debugger?
if self.interp.rpcclt:
- return self.open_remote_debugger()
- import Debugger
- self.interp.setdebugger(Debugger.Debugger(self))
- sys.ps1 = "[DEBUG ON]\n>>> "
- self.showprompt()
- self.set_debugger_indicator()
-
- def open_remote_debugger(self):
- gui = RemoteDebugger.start_remote_debugger(self.interp.rpcclt, self)
- self.interp.setdebugger(gui)
- # Load all PyShellEditorWindow breakpoints:
- gui.load_breakpoints()
+ dbg_gui = RemoteDebugger.start_remote_debugger(self.interp.rpcclt,
+ self)
+ else:
+ dbg_gui = Debugger.Debugger(self)
+ self.interp.setdebugger(dbg_gui)
+ dbg_gui.load_breakpoints()
sys.ps1 = "[DEBUG ON]\n>>> "
self.showprompt()
self.set_debugger_indicator()
@@ -779,18 +778,22 @@ class PyShell(OutputWindow):
"Kill?",
"The program is still running!\n Do you want to kill it?",
default="ok",
- master=self.text)
+ parent=self.text)
if response == False:
return "cancel"
# interrupt the subprocess
- self.closing = True
- self.endexecuting()
- return EditorWindow.close(self)
+ self.canceled = True
+ if use_subprocess:
+ self.interp.interrupt_subprocess()
+ return "cancel"
+ else:
+ return EditorWindow.close(self)
def _close(self):
"Extend EditorWindow._close(), shut down debugger and execution server"
self.close_debugger()
- self.interp.kill_subprocess()
+ if use_subprocess:
+ self.interp.kill_subprocess()
# Restore std streams
sys.stdout = self.save_stdout
sys.stderr = self.save_stderr
@@ -814,9 +817,13 @@ class PyShell(OutputWindow):
def begin(self):
self.resetoutput()
- self.write("Python %s on %s\n%s\nIDLEfork %s\n" %
+ if use_subprocess:
+ nosub = ''
+ else:
+ nosub = "==== No Subprocess ===="
+ self.write("Python %s on %s\n%s\nIDLEfork %s %s\n" %
(sys.version, sys.platform, self.COPYRIGHT,
- idlever.IDLE_VERSION))
+ idlever.IDLE_VERSION, nosub))
self.showprompt()
import Tkinter
Tkinter._default_root = None
@@ -853,7 +860,7 @@ class PyShell(OutputWindow):
pass
if not (self.executing or self.reading):
self.resetoutput()
- self.write("KeyboardInterrupt\n")
+ self.interp.write("KeyboardInterrupt\n")
self.showprompt()
return "break"
self.endoffile = 0
@@ -997,8 +1004,16 @@ class PyShell(OutputWindow):
self.text.see("restart")
def restart_shell(self, event=None):
- self.interp.restart_subprocess()
- self.showprompt()
+ if self.executing:
+ self.cancel_callback()
+ # Wait for subprocess to interrupt and restart
+ # This can be a long time if shell is scrolling on a slow system
+ # XXX 14 May 03 KBK This delay (and one in ScriptBinding) could be
+ # shorter if we didn't print the KeyboardInterrupt on
+ # restarting while user code is running....
+ self.text.after(2000, self.interp.restart_subprocess)
+ else:
+ self.interp.restart_subprocess()
def showprompt(self):
self.resetoutput()
@@ -1030,6 +1045,8 @@ class PyShell(OutputWindow):
pass
if self.canceled:
self.canceled = 0
+ if not use_subprocess:
+ raise KeyboardInterrupt
class PseudoFile:
diff --git a/Lib/idlelib/ScriptBinding.py b/Lib/idlelib/ScriptBinding.py
index 9604cb8..d404fc9 100644
--- a/Lib/idlelib/ScriptBinding.py
+++ b/Lib/idlelib/ScriptBinding.py
@@ -22,6 +22,7 @@ import string
import tabnanny
import tokenize
import tkMessageBox
+import PyShell
IDENTCHARS = string.ascii_letters + string.digits + "_"
@@ -38,8 +39,6 @@ To fix case 2, change all tabs to spaces by using Select All followed \
by Untabify Region (both in the Edit menu)."""
-# XXX 11Jun02 KBK TBD Implement stop-execution
-
class ScriptBinding:
menudefs = [
@@ -124,7 +123,19 @@ class ScriptBinding:
flist = self.editwin.flist
shell = flist.open_shell()
interp = shell.interp
- interp.restart_subprocess()
+ if PyShell.use_subprocess:
+ shell.restart_shell()
+ if shell.executing:
+ delay = 2700
+ else:
+ delay = 500
+ # Wait for the interrupt and reset to finish
+ shell.text.after(delay, self.run_module_event2, interp,
+ filename, code)
+ else:
+ self.run_module_event2(interp, filename, code)
+
+ def run_module_event2(self, interp, filename, code):
# XXX Too often this discards arguments the user just set...
interp.runcommand("""if 1:
_filename = %s