1 """Extension to execute code outside the Python shell window.
3 This adds the following commands (to the Edit menu, until there's a
6 - Check module (Alt-F5) does a full syntax check of the current module.
7 It also runs the tabnanny to catch any inconsistent tabs.
9 - Import module (F5) is equivalent to either import or reload of the
10 current module. The window must have been saved previously. The
11 module is added to sys.modules, and is also added to the __main__
12 namespace. Output goes to the shell window.
14 - Run module (Control-F5) does the same but executes the module's
15 code in the __main__ namespace.
24 indent_message
= """Error: Inconsistent indentation detected!
26 This means that either:
28 (1) your indentation is outright incorrect (easy to fix), or
30 (2) your indentation mixes tabs and spaces in a way that depends on \
31 how many spaces a tab is worth.
33 To fix case 2, change all tabs to spaces by using Select All followed \
34 by Untabify Region (both in the Edit menu)."""
39 '<<check-module>>': ['<Alt-F5>', '<Meta-F5>'],
40 '<<import-module>>': ['<F5>'],
41 '<<run-script>>': ['<Control-F5>'],
46 ('Check module', '<<check-module>>'),
47 ('Import module', '<<import-module>>'),
48 ('Run script', '<<run-script>>'),
53 def __init__(self
, editwin
):
54 self
.editwin
= editwin
55 # Provide instance variables referenced by Debugger
56 # XXX This should be done differently
57 self
.flist
= self
.editwin
.flist
58 self
.root
= self
.flist
.root
60 def check_module_event(self
, event
):
61 filename
= self
.getfilename()
64 if not self
.tabnanny(filename
):
66 if not self
.checksyntax(filename
):
69 def tabnanny(self
, filename
):
72 f
= open(filename
, 'r')
74 tabnanny
.process_tokens(tokenize
.generate_tokens(f
.readline
))
75 except tokenize
.TokenError
, msg
:
76 self
.errorbox("Token error",
77 "Token error:\n%s" % str(msg
))
79 except tabnanny
.NannyNag
, nag
:
80 # The error messages from tabnanny are too confusing...
81 self
.editwin
.gotoline(nag
.get_lineno())
82 self
.errorbox("Tab/space error", indent_message
)
86 def checksyntax(self
, filename
):
87 f
= open(filename
, 'r')
92 source
= re
.sub(r
"\r\n", "\n", source
)
93 if source
and source
[-1] != '\n':
94 source
= source
+ '\n'
96 compile(source
, filename
, "exec")
97 except (SyntaxError, OverflowError), err
:
99 msg
, (errorfilename
, lineno
, offset
, line
) = err
100 if not errorfilename
:
101 err
.args
= msg
, (filename
, lineno
, offset
, line
)
102 err
.filename
= filename
105 msg
= "*** " + str(err
)
107 self
.editwin
.gotoline(lineno
)
108 self
.errorbox("Syntax error",
109 "There's an error in your program:\n" + msg
)
112 def import_module_event(self
, event
):
113 filename
= self
.getfilename()
117 modname
, ext
= os
.path
.splitext(os
.path
.basename(filename
))
118 if sys
.modules
.has_key(modname
):
119 mod
= sys
.modules
[modname
]
121 mod
= imp
.new_module(modname
)
122 sys
.modules
[modname
] = mod
123 mod
.__file
__ = filename
124 setattr(sys
.modules
['__main__'], modname
, mod
)
126 dir = os
.path
.dirname(filename
)
127 dir = os
.path
.normpath(os
.path
.abspath(dir))
128 if dir not in sys
.path
:
129 sys
.path
.insert(0, dir)
131 flist
= self
.editwin
.flist
132 shell
= flist
.open_shell()
133 interp
= shell
.interp
134 interp
.runcode("reload(%s)" % modname
)
136 def run_script_event(self
, event
):
137 filename
= self
.getfilename()
141 flist
= self
.editwin
.flist
142 shell
= flist
.open_shell()
143 interp
= shell
.interp
145 os
.path
.basename(sys
.argv
[0]) != os
.path
.basename(filename
)):
146 # XXX Too often this discards arguments the user just set...
147 sys
.argv
= [filename
]
148 interp
.execfile(filename
)
150 def getfilename(self
):
151 # Logic to make sure we have a saved filename
152 # XXX Better logic would offer to save!
153 if not self
.editwin
.get_saved():
154 name
= (self
.editwin
.short_title() or
155 self
.editwin
.long_title() or
157 self
.errorbox("Not saved",
158 "The buffer for %s is not saved.\n" % name
+
159 "Please save it first!")
160 self
.editwin
.text
.focus_set()
162 filename
= self
.editwin
.io
.filename
164 self
.errorbox("No file name",
165 "This window has no file name")
169 def errorbox(self
, title
, message
):
170 # XXX This should really be a function of EditorWindow...
171 tkMessageBox
.showerror(title
, message
, master
=self
.editwin
.text
)
172 self
.editwin
.text
.focus_set()