| 
									
										
										
										
											2000-08-15 01:13:23 +00:00
										 |  |  | """Extension to execute code outside the Python shell window.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-06-12 03:28:57 +00:00
										 |  |  | This adds the following commands: | 
					
						
							| 
									
										
										
										
											2000-08-15 01:13:23 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-06-12 03:28:57 +00:00
										 |  |  | - Check module does a full syntax check of the current module. | 
					
						
							| 
									
										
										
										
											2000-08-15 01:13:23 +00:00
										 |  |  | It also runs the tabnanny to catch any inconsistent tabs. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-09-05 02:31:20 +00:00
										 |  |  | - Run module executes the module's code in the __main__ namespace.  The window | 
					
						
							|  |  |  | must have been saved previously. The module is added to sys.modules, and is | 
					
						
							|  |  |  | also added to the __main__ namespace. | 
					
						
							| 
									
										
										
										
											2000-08-15 01:13:23 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-05-26 13:36:41 +00:00
										 |  |  | XXX Redesign this interface (yet again) as follows: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | - Present a dialog box for ``Run script'' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | - Allow specify command line arguments in the dialog box | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-08-15 01:13:23 +00:00
										 |  |  | """
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import sys | 
					
						
							|  |  |  | import os | 
					
						
							|  |  |  | import imp | 
					
						
							|  |  |  | import tkMessageBox | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | indent_message = """Error: Inconsistent indentation detected!
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | This means that either: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-05-26 13:36:41 +00:00
										 |  |  | 1) your indentation is outright incorrect (easy to fix), or | 
					
						
							| 
									
										
										
										
											2000-08-15 01:13:23 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-05-26 13:36:41 +00:00
										 |  |  | 2) your indentation mixes tabs and spaces in a way that depends on \ | 
					
						
							| 
									
										
										
										
											2000-08-15 01:13:23 +00:00
										 |  |  | how many spaces a tab is worth. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | To fix case 2, change all tabs to spaces by using Select All followed \ | 
					
						
							|  |  |  | by Untabify Region (both in the Edit menu)."""
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-06-12 03:28:57 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | # XXX TBD Implement stop-execution  KBK 11Jun02 | 
					
						
							| 
									
										
										
										
											2000-08-15 01:13:23 +00:00
										 |  |  | class ScriptBinding: | 
					
						
							| 
									
										
										
										
											2001-07-12 06:46:53 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-08-15 01:13:23 +00:00
										 |  |  |     menudefs = [ | 
					
						
							| 
									
										
										
										
											2002-06-12 03:28:57 +00:00
										 |  |  |         ('run', [None, | 
					
						
							|  |  |  | #                 ('Check module', '<<check-module>>'), | 
					
						
							| 
									
										
										
										
											2000-08-15 01:13:23 +00:00
										 |  |  |                   ('Run script', '<<run-script>>'), | 
					
						
							|  |  |  |                  ] | 
					
						
							|  |  |  |         ), | 
					
						
							|  |  |  |     ] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __init__(self, editwin): | 
					
						
							|  |  |  |         self.editwin = editwin | 
					
						
							|  |  |  |         # Provide instance variables referenced by Debugger | 
					
						
							|  |  |  |         # XXX This should be done differently | 
					
						
							|  |  |  |         self.flist = self.editwin.flist | 
					
						
							|  |  |  |         self.root = self.flist.root | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def check_module_event(self, event): | 
					
						
							|  |  |  |         filename = self.getfilename() | 
					
						
							|  |  |  |         if not filename: | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  |         if not self.tabnanny(filename): | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  |         if not self.checksyntax(filename): | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def tabnanny(self, filename): | 
					
						
							|  |  |  |         import tabnanny | 
					
						
							|  |  |  |         import tokenize | 
					
						
							|  |  |  |         f = open(filename, 'r') | 
					
						
							|  |  |  |         try: | 
					
						
							| 
									
										
										
										
											2002-09-18 03:05:19 +00:00
										 |  |  |             tabnanny.process_tokens(tokenize.generate_tokens(f.readline)) | 
					
						
							| 
									
										
										
										
											2000-08-15 01:13:23 +00:00
										 |  |  |         except tokenize.TokenError, msg: | 
					
						
							|  |  |  |             self.errorbox("Token error", | 
					
						
							|  |  |  |                           "Token error:\n%s" % str(msg)) | 
					
						
							|  |  |  |             return 0 | 
					
						
							|  |  |  |         except tabnanny.NannyNag, nag: | 
					
						
							|  |  |  |             # The error messages from tabnanny are too confusing... | 
					
						
							|  |  |  |             self.editwin.gotoline(nag.get_lineno()) | 
					
						
							|  |  |  |             self.errorbox("Tab/space error", indent_message) | 
					
						
							|  |  |  |             return 0 | 
					
						
							|  |  |  |         return 1 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def checksyntax(self, filename): | 
					
						
							|  |  |  |         f = open(filename, 'r') | 
					
						
							|  |  |  |         source = f.read() | 
					
						
							|  |  |  |         f.close() | 
					
						
							|  |  |  |         if '\r' in source: | 
					
						
							|  |  |  |             import re | 
					
						
							|  |  |  |             source = re.sub(r"\r\n", "\n", source) | 
					
						
							|  |  |  |         if source and source[-1] != '\n': | 
					
						
							|  |  |  |             source = source + '\n' | 
					
						
							|  |  |  |         try: | 
					
						
							|  |  |  |             compile(source, filename, "exec") | 
					
						
							|  |  |  |         except (SyntaxError, OverflowError), err: | 
					
						
							|  |  |  |             try: | 
					
						
							|  |  |  |                 msg, (errorfilename, lineno, offset, line) = err | 
					
						
							|  |  |  |                 if not errorfilename: | 
					
						
							|  |  |  |                     err.args = msg, (filename, lineno, offset, line) | 
					
						
							|  |  |  |                     err.filename = filename | 
					
						
							|  |  |  |             except: | 
					
						
							|  |  |  |                 lineno = None | 
					
						
							|  |  |  |                 msg = "*** " + str(err) | 
					
						
							|  |  |  |             if lineno: | 
					
						
							|  |  |  |                 self.editwin.gotoline(lineno) | 
					
						
							|  |  |  |             self.errorbox("Syntax error", | 
					
						
							|  |  |  |                           "There's an error in your program:\n" + msg) | 
					
						
							|  |  |  |         return 1 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def run_script_event(self, event): | 
					
						
							|  |  |  |         filename = self.getfilename() | 
					
						
							|  |  |  |         if not filename: | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  |         flist = self.editwin.flist | 
					
						
							|  |  |  |         shell = flist.open_shell() | 
					
						
							|  |  |  |         interp = shell.interp | 
					
						
							| 
									
										
										
										
											2002-09-05 02:31:20 +00:00
										 |  |  |         if interp.tkconsole.executing: | 
					
						
							|  |  |  |             interp.display_executing_dialog() | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  |         interp.restart_subprocess() | 
					
						
							| 
									
										
										
										
											2002-05-26 13:36:41 +00:00
										 |  |  |         # XXX Too often this discards arguments the user just set... | 
					
						
							|  |  |  |         interp.runcommand("""if 1:
 | 
					
						
							|  |  |  |             _filename = %s | 
					
						
							|  |  |  |             import sys as _sys | 
					
						
							|  |  |  |             from os.path import basename as _basename | 
					
						
							|  |  |  |             if (not _sys.argv or | 
					
						
							|  |  |  |                 _basename(_sys.argv[0]) != _basename(_filename)): | 
					
						
							| 
									
										
										
										
											2002-07-28 03:35:31 +00:00
										 |  |  |                 # XXX 25 July 2002 KBK should this be sys.argv not _sys.argv? | 
					
						
							| 
									
										
										
										
											2002-05-26 13:36:41 +00:00
										 |  |  |                 _sys.argv = [_filename] | 
					
						
							|  |  |  |             del _filename, _sys, _basename | 
					
						
							|  |  |  |                 \n""" % `filename`)
 | 
					
						
							| 
									
										
										
										
											2000-08-15 01:13:23 +00:00
										 |  |  |         interp.execfile(filename) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def getfilename(self): | 
					
						
							|  |  |  |         # Logic to make sure we have a saved filename | 
					
						
							|  |  |  |         # XXX Better logic would offer to save! | 
					
						
							|  |  |  |         if not self.editwin.get_saved(): | 
					
						
							| 
									
										
										
										
											2001-07-12 06:46:53 +00:00
										 |  |  |             name = (self.editwin.short_title() or | 
					
						
							|  |  |  |                     self.editwin.long_title() or | 
					
						
							|  |  |  |                     "Untitled") | 
					
						
							| 
									
										
										
										
											2000-08-15 01:13:23 +00:00
										 |  |  |             self.errorbox("Not saved", | 
					
						
							| 
									
										
										
										
											2001-07-12 06:46:53 +00:00
										 |  |  |                           "The buffer for %s is not saved.\n" % name + | 
					
						
							|  |  |  |                           "Please save it first!") | 
					
						
							| 
									
										
										
										
											2000-08-15 01:13:23 +00:00
										 |  |  |             self.editwin.text.focus_set() | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  |         filename = self.editwin.io.filename | 
					
						
							|  |  |  |         if not filename: | 
					
						
							|  |  |  |             self.errorbox("No file name", | 
					
						
							|  |  |  |                           "This window has no file name") | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  |         return filename | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def errorbox(self, title, message): | 
					
						
							|  |  |  |         # XXX This should really be a function of EditorWindow... | 
					
						
							|  |  |  |         tkMessageBox.showerror(title, message, master=self.editwin.text) | 
					
						
							|  |  |  |         self.editwin.text.focus_set() |