blob: a1a7f2cf8a47f8470686aea20c7fecd5589a8164 [file] [log] [blame]
Guido van Rossum9f425841999-01-09 05:00:17 +00001"""Extension to execute code outside the Python shell window.
2
3This adds two commands (to the Edit menu, until there's a separate
4Python menu):
5
6- Run module (F5) is equivalent to either import or reload of the
7current module. The window must have been saved previously. The
8module only gets added to sys.modules, it doesn't get added to
9anyone's namespace; you can import it in the shell if you need to. If
10this generates any output to sys.stdout or sys.stderr, a new output
11window is created to display that output. The two streams are
12distinguished by their text color.
13
14- Debug module (Control-F5) does the same but executes the module's
15code in the debugger.
16
17When an unhandled exception occurs in Run module, the stack viewer is
18popped up. This is not done in Debug module, because you've already
19had an opportunity to view the stack. In either case, the variables
20sys.last_type, sys.last_value, sys.last_traceback are set to the
21exception info.
22
23"""
24
25import sys
Guido van Rossum504b0bf1999-01-02 21:28:54 +000026import os
27import imp
Guido van Rossum9f425841999-01-09 05:00:17 +000028import linecache
29import traceback
30import tkMessageBox
31from OutputWindow import OutputWindow
32
33# XXX These helper classes are more generally usable!
34
35class OnDemandOutputWindow:
36
37 tagdefs = {
38 "stdout": {"foreground": "blue"},
39 "stderr": {"foreground": "#007700"},
40 }
41
42 def __init__(self, flist):
43 self.flist = flist
44 self.owin = None
45
46 def write(self, s, tags, mark):
47 if not self.owin:
48 self.setup()
49 self.owin.write(s, tags, mark)
50
51 def setup(self):
52 self.owin = owin = OutputWindow(self.flist)
53 text = owin.text
54 for tag, cnf in self.tagdefs.items():
55 if cnf:
56 apply(text.tag_configure, (tag,), cnf)
57 text.tag_raise('sel')
58 self.write = self.owin.write
59
60class PseudoFile:
61
62 def __init__(self, owin, tags, mark="end"):
63 self.owin = owin
64 self.tags = tags
65 self.mark = mark
66
67 def write(self, s):
68 self.owin.write(s, self.tags, self.mark)
69
70 def writelines(self, l):
71 map(self.write, l)
72
Guido van Rossum825df2a1999-03-29 14:52:28 +000073 def flush(self):
74 pass
75
Guido van Rossum504b0bf1999-01-02 21:28:54 +000076
77class ScriptBinding:
Guido van Rossum9f425841999-01-09 05:00:17 +000078
79 keydefs = {
80 '<<run-module>>': ['<F5>'],
81 '<<debug-module>>': ['<Control-F5>'],
82 }
83
84 menudefs = [
85 ('edit', [None,
86 ('Run module', '<<run-module>>'),
87 ('Debug module', '<<debug-module>>'),
88 ]
89 ),
90 ]
Guido van Rossum504b0bf1999-01-02 21:28:54 +000091
92 def __init__(self, editwin):
93 self.editwin = editwin
Guido van Rossum9f425841999-01-09 05:00:17 +000094 # Provide instance variables referenced by Debugger
95 # XXX This should be done differently
96 self.flist = self.editwin.flist
97 self.root = self.flist.root
Guido van Rossum504b0bf1999-01-02 21:28:54 +000098
Guido van Rossum9f425841999-01-09 05:00:17 +000099 def run_module_event(self, event, debugger=None):
100 if not self.editwin.get_saved():
101 tkMessageBox.showerror("Not saved",
102 "Please save first!",
103 master=self.editwin.text)
104 self.editwin.text.focus_set()
105 return
Guido van Rossum504b0bf1999-01-02 21:28:54 +0000106 filename = self.editwin.io.filename
107 if not filename:
108 tkMessageBox.showerror("No file name",
109 "This window has no file name",
110 master=self.editwin.text)
Guido van Rossum9f425841999-01-09 05:00:17 +0000111 self.editwin.text.focus_set()
Guido van Rossum504b0bf1999-01-02 21:28:54 +0000112 return
113 modname, ext = os.path.splitext(os.path.basename(filename))
Guido van Rossum9f425841999-01-09 05:00:17 +0000114 if sys.modules.has_key(modname):
Guido van Rossum504b0bf1999-01-02 21:28:54 +0000115 mod = sys.modules[modname]
Guido van Rossum9f425841999-01-09 05:00:17 +0000116 else:
Guido van Rossum504b0bf1999-01-02 21:28:54 +0000117 mod = imp.new_module(modname)
118 sys.modules[modname] = mod
Guido van Rossum9f425841999-01-09 05:00:17 +0000119 mod.__file__ = filename
120 saveout = sys.stdout
121 saveerr = sys.stderr
122 owin = OnDemandOutputWindow(self.editwin.flist)
123 try:
124 sys.stderr = PseudoFile(owin, "stderr")
125 try:
126 sys.stdout = PseudoFile(owin, "stdout")
127 try:
128 if debugger:
129 debugger.run("execfile(%s)" % `filename`, mod.__dict__)
130 else:
131 execfile(filename, mod.__dict__)
132 except:
133 (sys.last_type, sys.last_value,
134 sys.last_traceback) = sys.exc_info()
Guido van Rossumd5c84971999-01-11 14:47:54 +0000135 linecache.checkcache()
136 traceback.print_exc()
Guido van Rossum9ea32891999-02-16 22:34:17 +0000137 if not debugger and \
138 self.editwin.getvar("<<toggle-jit-stack-viewer>>"):
Guido van Rossum9f425841999-01-09 05:00:17 +0000139 from StackViewer import StackBrowser
140 sv = StackBrowser(self.root, self.flist)
141 finally:
142 sys.stdout = saveout
143 finally:
144 sys.stderr = saveerr
Guido van Rossum504b0bf1999-01-02 21:28:54 +0000145
Guido van Rossum9f425841999-01-09 05:00:17 +0000146 def debug_module_event(self, event):
147 import Debugger
148 debugger = Debugger.Debugger(self)
149 self.run_module_event(event, debugger)
150
151 def close_debugger(self):
152 # Method called by Debugger
153 # XXX This should be done differently
Guido van Rossum504b0bf1999-01-02 21:28:54 +0000154 pass