mirror of
				https://github.com/python/cpython.git
				synced 2025-10-30 21:21:22 +00:00 
			
		
		
		
	
		
			
	
	
		
			170 lines
		
	
	
	
		
			5.4 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
		
		
			
		
	
	
			170 lines
		
	
	
	
		
			5.4 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
|   | """Extension to execute code outside the Python shell window.
 | ||
|  | 
 | ||
|  | This adds the following commands (to the Edit menu, until there's a | ||
|  | separate Python menu): | ||
|  | 
 | ||
|  | - Check module (Alt-F5) does a full syntax check of the current module. | ||
|  | It also runs the tabnanny to catch any inconsistent tabs. | ||
|  | 
 | ||
|  | - Import module (F5) is equivalent to either import or reload of the | ||
|  | current module.  The window must have been saved previously. The | ||
|  | module is added to sys.modules, and is also added to the __main__ | ||
|  | namespace.  Output goes to the shell window. | ||
|  | 
 | ||
|  | - Run module (Control-F5) does the same but executes the module's | ||
|  | code in the __main__ namespace. | ||
|  | 
 | ||
|  | """
 | ||
|  | 
 | ||
|  | import sys | ||
|  | import os | ||
|  | import imp | ||
|  | import tkMessageBox | ||
|  | 
 | ||
|  | indent_message = """Error: Inconsistent indentation detected!
 | ||
|  | 
 | ||
|  | This means that either: | ||
|  | 
 | ||
|  | (1) your indentation is outright incorrect (easy to fix), or | ||
|  | 
 | ||
|  | (2) your indentation mixes tabs and spaces in a way that depends on \ | ||
|  | 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)."""
 | ||
|  | 
 | ||
|  | class ScriptBinding: | ||
|  |      | ||
|  |     keydefs = { | ||
|  |         '<<check-module>>': ['<Alt-F5>', '<Meta-F5>'], | ||
|  |         '<<import-module>>': ['<F5>'], | ||
|  |         '<<run-script>>': ['<Control-F5>'], | ||
|  |     } | ||
|  |      | ||
|  |     menudefs = [ | ||
|  |         ('edit', [None, | ||
|  |                   ('Check module', '<<check-module>>'), | ||
|  |                   ('Import module', '<<import-module>>'), | ||
|  |                   ('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 | ||
|  |         tabnanny.reset_globals() | ||
|  |         f = open(filename, 'r') | ||
|  |         try: | ||
|  |             tokenize.tokenize(f.readline, tabnanny.tokeneater) | ||
|  |         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 import_module_event(self, event): | ||
|  |         filename = self.getfilename() | ||
|  |         if not filename: | ||
|  |             return | ||
|  | 
 | ||
|  |         modname, ext = os.path.splitext(os.path.basename(filename)) | ||
|  |         if sys.modules.has_key(modname): | ||
|  |             mod = sys.modules[modname] | ||
|  |         else: | ||
|  |             mod = imp.new_module(modname) | ||
|  |             sys.modules[modname] = mod | ||
|  |         mod.__file__ = filename | ||
|  |         setattr(sys.modules['__main__'], modname, mod) | ||
|  | 
 | ||
|  |         dir = os.path.dirname(filename) | ||
|  |         dir = os.path.normpath(os.path.abspath(dir)) | ||
|  |         if dir not in sys.path: | ||
|  |             sys.path.insert(0, dir) | ||
|  | 
 | ||
|  |         flist = self.editwin.flist | ||
|  |         shell = flist.open_shell() | ||
|  |         interp = shell.interp | ||
|  |         interp.runcode("reload(%s)" % modname) | ||
|  | 
 | ||
|  |     def run_script_event(self, event): | ||
|  |         filename = self.getfilename() | ||
|  |         if not filename: | ||
|  |             return | ||
|  | 
 | ||
|  |         flist = self.editwin.flist | ||
|  |         shell = flist.open_shell() | ||
|  |         interp = shell.interp | ||
|  |         if (not sys.argv or | ||
|  |             os.path.basename(sys.argv[0]) != os.path.basename(filename)): | ||
|  |             # XXX Too often this discards arguments the user just set... | ||
|  |             sys.argv = [filename] | ||
|  |         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(): | ||
|  |             self.errorbox("Not saved", | ||
|  |                           "Please save first!") | ||
|  |             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() |