symbian-qemu-0.9.1-12/python-2.6.1/Lib/idlelib/ScriptBinding.py
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 """Extension to execute code outside the Python shell window.
       
     2 
       
     3 This adds the following commands:
       
     4 
       
     5 - Check module does a full syntax check of the current module.
       
     6   It also runs the tabnanny to catch any inconsistent tabs.
       
     7 
       
     8 - Run module executes the module's code in the __main__ namespace.  The window
       
     9   must have been saved previously. The module is added to sys.modules, and is
       
    10   also added to the __main__ namespace.
       
    11 
       
    12 XXX GvR Redesign this interface (yet again) as follows:
       
    13 
       
    14 - Present a dialog box for ``Run Module''
       
    15 
       
    16 - Allow specify command line arguments in the dialog box
       
    17 
       
    18 """
       
    19 
       
    20 import os
       
    21 import re
       
    22 import string
       
    23 import tabnanny
       
    24 import tokenize
       
    25 import tkMessageBox
       
    26 import PyShell
       
    27 
       
    28 from configHandler import idleConf
       
    29 
       
    30 IDENTCHARS = string.ascii_letters + string.digits + "_"
       
    31 
       
    32 indent_message = """Error: Inconsistent indentation detected!
       
    33 
       
    34 1) Your indentation is outright incorrect (easy to fix), OR
       
    35 
       
    36 2) Your indentation mixes tabs and spaces.
       
    37 
       
    38 To fix case 2, change all tabs to spaces by using Edit->Select All followed \
       
    39 by Format->Untabify Region and specify the number of columns used by each tab.
       
    40 """
       
    41 
       
    42 class ScriptBinding:
       
    43 
       
    44     menudefs = [
       
    45         ('run', [None,
       
    46                  ('Check Module', '<<check-module>>'),
       
    47                  ('Run Module', '<<run-module>>'), ]), ]
       
    48 
       
    49     def __init__(self, editwin):
       
    50         self.editwin = editwin
       
    51         # Provide instance variables referenced by Debugger
       
    52         # XXX This should be done differently
       
    53         self.flist = self.editwin.flist
       
    54         self.root = self.editwin.root
       
    55 
       
    56     def check_module_event(self, event):
       
    57         filename = self.getfilename()
       
    58         if not filename:
       
    59             return 'break'
       
    60         if not self.checksyntax(filename):
       
    61             return 'break'
       
    62         if not self.tabnanny(filename):
       
    63             return 'break'
       
    64 
       
    65     def tabnanny(self, filename):
       
    66         f = open(filename, 'r')
       
    67         try:
       
    68             tabnanny.process_tokens(tokenize.generate_tokens(f.readline))
       
    69         except tokenize.TokenError, msg:
       
    70             msgtxt, (lineno, start) = msg
       
    71             self.editwin.gotoline(lineno)
       
    72             self.errorbox("Tabnanny Tokenizing Error",
       
    73                           "Token Error: %s" % msgtxt)
       
    74             return False
       
    75         except tabnanny.NannyNag, nag:
       
    76             # The error messages from tabnanny are too confusing...
       
    77             self.editwin.gotoline(nag.get_lineno())
       
    78             self.errorbox("Tab/space error", indent_message)
       
    79             return False
       
    80         return True
       
    81 
       
    82     def checksyntax(self, filename):
       
    83         self.shell = shell = self.flist.open_shell()
       
    84         saved_stream = shell.get_warning_stream()
       
    85         shell.set_warning_stream(shell.stderr)
       
    86         f = open(filename, 'r')
       
    87         source = f.read()
       
    88         f.close()
       
    89         if '\r' in source:
       
    90             source = re.sub(r"\r\n", "\n", source)
       
    91             source = re.sub(r"\r", "\n", source)
       
    92         if source and source[-1] != '\n':
       
    93             source = source + '\n'
       
    94         text = self.editwin.text
       
    95         text.tag_remove("ERROR", "1.0", "end")
       
    96         try:
       
    97             try:
       
    98                 # If successful, return the compiled code
       
    99                 return compile(source, filename, "exec")
       
   100             except (SyntaxError, OverflowError), err:
       
   101                 try:
       
   102                     msg, (errorfilename, lineno, offset, line) = err
       
   103                     if not errorfilename:
       
   104                         err.args = msg, (filename, lineno, offset, line)
       
   105                         err.filename = filename
       
   106                     self.colorize_syntax_error(msg, lineno, offset)
       
   107                 except:
       
   108                     msg = "*** " + str(err)
       
   109                 self.errorbox("Syntax error",
       
   110                               "There's an error in your program:\n" + msg)
       
   111                 return False
       
   112         finally:
       
   113             shell.set_warning_stream(saved_stream)
       
   114 
       
   115     def colorize_syntax_error(self, msg, lineno, offset):
       
   116         text = self.editwin.text
       
   117         pos = "0.0 + %d lines + %d chars" % (lineno-1, offset-1)
       
   118         text.tag_add("ERROR", pos)
       
   119         char = text.get(pos)
       
   120         if char and char in IDENTCHARS:
       
   121             text.tag_add("ERROR", pos + " wordstart", pos)
       
   122         if '\n' == text.get(pos):   # error at line end
       
   123             text.mark_set("insert", pos)
       
   124         else:
       
   125             text.mark_set("insert", pos + "+1c")
       
   126         text.see(pos)
       
   127 
       
   128     def run_module_event(self, event):
       
   129         """Run the module after setting up the environment.
       
   130 
       
   131         First check the syntax.  If OK, make sure the shell is active and
       
   132         then transfer the arguments, set the run environment's working
       
   133         directory to the directory of the module being executed and also
       
   134         add that directory to its sys.path if not already included.
       
   135 
       
   136         """
       
   137         filename = self.getfilename()
       
   138         if not filename:
       
   139             return 'break'
       
   140         code = self.checksyntax(filename)
       
   141         if not code:
       
   142             return 'break'
       
   143         if not self.tabnanny(filename):
       
   144             return 'break'
       
   145         shell = self.shell
       
   146         interp = shell.interp
       
   147         if PyShell.use_subprocess:
       
   148             shell.restart_shell()
       
   149         dirname = os.path.dirname(filename)
       
   150         # XXX Too often this discards arguments the user just set...
       
   151         interp.runcommand("""if 1:
       
   152             _filename = %r
       
   153             import sys as _sys
       
   154             from os.path import basename as _basename
       
   155             if (not _sys.argv or
       
   156                 _basename(_sys.argv[0]) != _basename(_filename)):
       
   157                 _sys.argv = [_filename]
       
   158             import os as _os
       
   159             _os.chdir(%r)
       
   160             del _filename, _sys, _basename, _os
       
   161             \n""" % (filename, dirname))
       
   162         interp.prepend_syspath(filename)
       
   163         # XXX KBK 03Jul04 When run w/o subprocess, runtime warnings still
       
   164         #         go to __stderr__.  With subprocess, they go to the shell.
       
   165         #         Need to change streams in PyShell.ModifiedInterpreter.
       
   166         interp.runcode(code)
       
   167         return 'break'
       
   168 
       
   169     def getfilename(self):
       
   170         """Get source filename.  If not saved, offer to save (or create) file
       
   171 
       
   172         The debugger requires a source file.  Make sure there is one, and that
       
   173         the current version of the source buffer has been saved.  If the user
       
   174         declines to save or cancels the Save As dialog, return None.
       
   175 
       
   176         If the user has configured IDLE for Autosave, the file will be
       
   177         silently saved if it already exists and is dirty.
       
   178 
       
   179         """
       
   180         filename = self.editwin.io.filename
       
   181         if not self.editwin.get_saved():
       
   182             autosave = idleConf.GetOption('main', 'General',
       
   183                                           'autosave', type='bool')
       
   184             if autosave and filename:
       
   185                 self.editwin.io.save(None)
       
   186             else:
       
   187                 reply = self.ask_save_dialog()
       
   188                 self.editwin.text.focus_set()
       
   189                 if reply == "ok":
       
   190                     self.editwin.io.save(None)
       
   191                     filename = self.editwin.io.filename
       
   192                 else:
       
   193                     filename = None
       
   194         return filename
       
   195 
       
   196     def ask_save_dialog(self):
       
   197         msg = "Source Must Be Saved\n" + 5*' ' + "OK to Save?"
       
   198         mb = tkMessageBox.Message(title="Save Before Run or Check",
       
   199                                   message=msg,
       
   200                                   icon=tkMessageBox.QUESTION,
       
   201                                   type=tkMessageBox.OKCANCEL,
       
   202                                   default=tkMessageBox.OK,
       
   203                                   master=self.editwin.text)
       
   204         return mb.show()
       
   205 
       
   206     def errorbox(self, title, message):
       
   207         # XXX This should really be a function of EditorWindow...
       
   208         tkMessageBox.showerror(title, message, master=self.editwin.text)
       
   209         self.editwin.text.focus_set()