blob: 12dedb6581b3954d2ff65e7b3aac1a63c6176e5f [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 Rossum504b0bf1999-01-02 21:28:54 +000073
74class ScriptBinding:
Guido van Rossum9f425841999-01-09 05:00:17 +000075
76 keydefs = {
77 '<<run-module>>': ['<F5>'],
78 '<<debug-module>>': ['<Control-F5>'],
79 }
80
81 menudefs = [
82 ('edit', [None,
83 ('Run module', '<<run-module>>'),
84 ('Debug module', '<<debug-module>>'),
85 ]
86 ),
87 ]
Guido van Rossum504b0bf1999-01-02 21:28:54 +000088
89 def __init__(self, editwin):
90 self.editwin = editwin
Guido van Rossum9f425841999-01-09 05:00:17 +000091 # Provide instance variables referenced by Debugger
92 # XXX This should be done differently
93 self.flist = self.editwin.flist
94 self.root = self.flist.root
Guido van Rossum504b0bf1999-01-02 21:28:54 +000095
Guido van Rossum9f425841999-01-09 05:00:17 +000096 def run_module_event(self, event, debugger=None):
97 if not self.editwin.get_saved():
98 tkMessageBox.showerror("Not saved",
99 "Please save first!",
100 master=self.editwin.text)
101 self.editwin.text.focus_set()
102 return
Guido van Rossum504b0bf1999-01-02 21:28:54 +0000103 filename = self.editwin.io.filename
104 if not filename:
105 tkMessageBox.showerror("No file name",
106 "This window has no file name",
107 master=self.editwin.text)
Guido van Rossum9f425841999-01-09 05:00:17 +0000108 self.editwin.text.focus_set()
Guido van Rossum504b0bf1999-01-02 21:28:54 +0000109 return
110 modname, ext = os.path.splitext(os.path.basename(filename))
Guido van Rossum9f425841999-01-09 05:00:17 +0000111 if sys.modules.has_key(modname):
Guido van Rossum504b0bf1999-01-02 21:28:54 +0000112 mod = sys.modules[modname]
Guido van Rossum9f425841999-01-09 05:00:17 +0000113 else:
Guido van Rossum504b0bf1999-01-02 21:28:54 +0000114 mod = imp.new_module(modname)
115 sys.modules[modname] = mod
Guido van Rossum9f425841999-01-09 05:00:17 +0000116 mod.__file__ = filename
117 saveout = sys.stdout
118 saveerr = sys.stderr
119 owin = OnDemandOutputWindow(self.editwin.flist)
120 try:
121 sys.stderr = PseudoFile(owin, "stderr")
122 try:
123 sys.stdout = PseudoFile(owin, "stdout")
124 try:
125 if debugger:
126 debugger.run("execfile(%s)" % `filename`, mod.__dict__)
127 else:
128 execfile(filename, mod.__dict__)
129 except:
130 (sys.last_type, sys.last_value,
131 sys.last_traceback) = sys.exc_info()
Guido van Rossumd5c84971999-01-11 14:47:54 +0000132 linecache.checkcache()
133 traceback.print_exc()
Guido van Rossum9f425841999-01-09 05:00:17 +0000134 if not debugger:
135 from StackViewer import StackBrowser
136 sv = StackBrowser(self.root, self.flist)
137 finally:
138 sys.stdout = saveout
139 finally:
140 sys.stderr = saveerr
Guido van Rossum504b0bf1999-01-02 21:28:54 +0000141
Guido van Rossum9f425841999-01-09 05:00:17 +0000142 def debug_module_event(self, event):
143 import Debugger
144 debugger = Debugger.Debugger(self)
145 self.run_module_event(event, debugger)
146
147 def close_debugger(self):
148 # Method called by Debugger
149 # XXX This should be done differently
Guido van Rossum504b0bf1999-01-02 21:28:54 +0000150 pass