This now actually works. See doc string. It can run a module (i.e.

import or reload) or debug it (same with debugger control).  Output
goes to a fresh output window, only created when needed.
This commit is contained in:
Guido van Rossum 1999-01-09 05:00:17 +00:00
parent 5d00b6d459
commit 9f42584907
1 changed files with 130 additions and 18 deletions

View File

@ -1,38 +1,150 @@
import tkMessageBox
"""Extension to execute code outside the Python shell window.
This adds two commands (to the Edit menu, until there's a separate
Python menu):
- Run module (F5) is equivalent to either import or reload of the
current module. The window must have been saved previously. The
module only gets added to sys.modules, it doesn't get added to
anyone's namespace; you can import it in the shell if you need to. If
this generates any output to sys.stdout or sys.stderr, a new output
window is created to display that output. The two streams are
distinguished by their text color.
- Debug module (Control-F5) does the same but executes the module's
code in the debugger.
When an unhandled exception occurs in Run module, the stack viewer is
popped up. This is not done in Debug module, because you've already
had an opportunity to view the stack. In either case, the variables
sys.last_type, sys.last_value, sys.last_traceback are set to the
exception info.
"""
import sys
import os
import imp
import sys
import linecache
import traceback
import tkMessageBox
from OutputWindow import OutputWindow
# XXX These helper classes are more generally usable!
class OnDemandOutputWindow:
tagdefs = {
"stdout": {"foreground": "blue"},
"stderr": {"foreground": "#007700"},
}
def __init__(self, flist):
self.flist = flist
self.owin = None
def write(self, s, tags, mark):
if not self.owin:
self.setup()
self.owin.write(s, tags, mark)
def setup(self):
self.owin = owin = OutputWindow(self.flist)
text = owin.text
for tag, cnf in self.tagdefs.items():
if cnf:
apply(text.tag_configure, (tag,), cnf)
text.tag_raise('sel')
self.write = self.owin.write
class PseudoFile:
def __init__(self, owin, tags, mark="end"):
self.owin = owin
self.tags = tags
self.mark = mark
def write(self, s):
self.owin.write(s, self.tags, self.mark)
def writelines(self, l):
map(self.write, l)
class ScriptBinding:
keydefs = {
'<<run-module>>': ['<F5>'],
'<<debug-module>>': ['<Control-F5>'],
}
menudefs = [
('edit', [None,
('Run module', '<<run-module>>'),
('Debug module', '<<debug-module>>'),
]
),
]
def __init__(self, editwin):
self.editwin = editwin
text = editwin.text
text.bind("<<run-module>>", self.run_module)
text.bind("<<run-script>>", self.run_script)
text.bind("<<new-shell>>", self.new_shell)
# Provide instance variables referenced by Debugger
# XXX This should be done differently
self.flist = self.editwin.flist
self.root = self.flist.root
def run_module(self, event=None):
def run_module_event(self, event, debugger=None):
if not self.editwin.get_saved():
tkMessageBox.showerror("Not saved",
"Please save first!",
master=self.editwin.text)
self.editwin.text.focus_set()
return
filename = self.editwin.io.filename
if not filename:
tkMessageBox.showerror("No file name",
"This window has no file name",
master=self.editwin.text)
self.editwin.text.focus_set()
return
modname, ext = os.path.splitext(os.path.basename(filename))
try:
if sys.modules.has_key(modname):
mod = sys.modules[modname]
except KeyError:
else:
mod = imp.new_module(modname)
sys.modules[modname] = mod
source = self.editwin.text.get("1.0", "end")
exec source in mod.__dict__
mod.__file__ = filename
saveout = sys.stdout
saveerr = sys.stderr
owin = OnDemandOutputWindow(self.editwin.flist)
try:
sys.stderr = PseudoFile(owin, "stderr")
try:
sys.stdout = PseudoFile(owin, "stdout")
try:
if debugger:
debugger.run("execfile(%s)" % `filename`, mod.__dict__)
else:
execfile(filename, mod.__dict__)
except:
(sys.last_type, sys.last_value,
sys.last_traceback) = sys.exc_info()
## linecache.checkcache()
## traceback.print_exc()
if not debugger:
from StackViewer import StackBrowser
sv = StackBrowser(self.root, self.flist)
finally:
sys.stdout = saveout
finally:
sys.stderr = saveerr
def run_script(self, event=None):
def debug_module_event(self, event):
import Debugger
debugger = Debugger.Debugger(self)
self.run_module_event(event, debugger)
def close_debugger(self):
# Method called by Debugger
# XXX This should be done differently
pass
def new_shell(self, event=None):
import PyShell
# XXX Not enough: each shell takes over stdin/stdout/stderr...
pyshell = PyShell.PyShell(self.editwin.flist)
pyshell.begin()