symbian-qemu-0.9.1-12/python-2.6.1/Tools/pybench/CommandLine.py
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 """ CommandLine - Get and parse command line options
       
     2 
       
     3     NOTE: This still is very much work in progress !!!
       
     4 
       
     5     Different version are likely to be incompatible.
       
     6 
       
     7     TODO:
       
     8 
       
     9     * Incorporate the changes made by (see Inbox)
       
    10     * Add number range option using srange()
       
    11 
       
    12 """
       
    13 
       
    14 __copyright__ = """\
       
    15 Copyright (c), 1997-2006, Marc-Andre Lemburg (mal@lemburg.com)
       
    16 Copyright (c), 2000-2006, eGenix.com Software GmbH (info@egenix.com)
       
    17 See the documentation for further information on copyrights,
       
    18 or contact the author. All Rights Reserved.
       
    19 """
       
    20 
       
    21 __version__ = '1.2'
       
    22 
       
    23 import sys, getopt, string, glob, os, re, exceptions, traceback
       
    24 
       
    25 ### Helpers
       
    26 
       
    27 def _getopt_flags(options):
       
    28 
       
    29     """ Convert the option list to a getopt flag string and long opt
       
    30         list
       
    31 
       
    32     """
       
    33     s = []
       
    34     l = []
       
    35     for o in options:
       
    36         if o.prefix == '-':
       
    37             # short option
       
    38             s.append(o.name)
       
    39             if o.takes_argument:
       
    40                 s.append(':')
       
    41         else:
       
    42             # long option
       
    43             if o.takes_argument:
       
    44                 l.append(o.name+'=')
       
    45             else:
       
    46                 l.append(o.name)
       
    47     return string.join(s,''),l
       
    48 
       
    49 def invisible_input(prompt='>>> '):
       
    50 
       
    51     """ Get raw input from a terminal without echoing the characters to
       
    52         the terminal, e.g. for password queries.
       
    53 
       
    54     """
       
    55     import getpass
       
    56     entry = getpass.getpass(prompt)
       
    57     if entry is None:
       
    58         raise KeyboardInterrupt
       
    59     return entry
       
    60 
       
    61 def fileopen(name, mode='wb', encoding=None):
       
    62 
       
    63     """ Open a file using mode.
       
    64 
       
    65         Default mode is 'wb' meaning to open the file for writing in
       
    66         binary mode. If encoding is given, I/O to and from the file is
       
    67         transparently encoded using the given encoding.
       
    68 
       
    69         Files opened for writing are chmod()ed to 0600.
       
    70 
       
    71     """
       
    72     if name == 'stdout':
       
    73         return sys.stdout
       
    74     elif name == 'stderr':
       
    75         return sys.stderr
       
    76     elif name == 'stdin':
       
    77         return sys.stdin
       
    78     else:
       
    79         if encoding is not None:
       
    80             import codecs
       
    81             f = codecs.open(name, mode, encoding)
       
    82         else:
       
    83             f = open(name, mode)
       
    84         if 'w' in mode:
       
    85             os.chmod(name, 0600)
       
    86         return f
       
    87 
       
    88 def option_dict(options):
       
    89 
       
    90     """ Return a dictionary mapping option names to Option instances.
       
    91     """
       
    92     d = {}
       
    93     for option in options:
       
    94         d[option.name] = option
       
    95     return d
       
    96 
       
    97 # Alias
       
    98 getpasswd = invisible_input
       
    99 
       
   100 _integerRE = re.compile('\s*(-?\d+)\s*$')
       
   101 _integerRangeRE = re.compile('\s*(-?\d+)\s*-\s*(-?\d+)\s*$')
       
   102 
       
   103 def srange(s,
       
   104 
       
   105            split=string.split,integer=_integerRE,
       
   106            integerRange=_integerRangeRE):
       
   107 
       
   108     """ Converts a textual representation of integer numbers and ranges
       
   109         to a Python list.
       
   110 
       
   111         Supported formats: 2,3,4,2-10,-1 - -3, 5 - -2
       
   112 
       
   113         Values are appended to the created list in the order specified
       
   114         in the string.
       
   115 
       
   116     """
       
   117     l = []
       
   118     append = l.append
       
   119     for entry in split(s,','):
       
   120         m = integer.match(entry)
       
   121         if m:
       
   122             append(int(m.groups()[0]))
       
   123             continue
       
   124         m = integerRange.match(entry)
       
   125         if m:
       
   126             start,end = map(int,m.groups())
       
   127             l[len(l):] = range(start,end+1)
       
   128     return l
       
   129 
       
   130 def abspath(path,
       
   131 
       
   132             expandvars=os.path.expandvars,expanduser=os.path.expanduser,
       
   133             join=os.path.join,getcwd=os.getcwd):
       
   134 
       
   135     """ Return the corresponding absolute path for path.
       
   136 
       
   137         path is expanded in the usual shell ways before
       
   138         joining it with the current working directory.
       
   139 
       
   140     """
       
   141     try:
       
   142         path = expandvars(path)
       
   143     except AttributeError:
       
   144         pass
       
   145     try:
       
   146         path = expanduser(path)
       
   147     except AttributeError:
       
   148         pass
       
   149     return join(getcwd(), path)
       
   150 
       
   151 ### Option classes
       
   152 
       
   153 class Option:
       
   154 
       
   155     """ Option base class. Takes no argument.
       
   156 
       
   157     """
       
   158     default = None
       
   159     helptext = ''
       
   160     prefix = '-'
       
   161     takes_argument = 0
       
   162     has_default = 0
       
   163     tab = 15
       
   164 
       
   165     def __init__(self,name,help=None):
       
   166 
       
   167         if not name[:1] == '-':
       
   168             raise TypeError,'option names must start with "-"'
       
   169         if name[1:2] == '-':
       
   170             self.prefix = '--'
       
   171             self.name = name[2:]
       
   172         else:
       
   173             self.name = name[1:]
       
   174         if help:
       
   175             self.help = help
       
   176 
       
   177     def __str__(self):
       
   178 
       
   179         o = self
       
   180         name = o.prefix + o.name
       
   181         if o.takes_argument:
       
   182             name = name + ' arg'
       
   183         if len(name) > self.tab:
       
   184             name = name + '\n' + ' ' * (self.tab + 1 + len(o.prefix))
       
   185         else:
       
   186             name = '%-*s ' % (self.tab, name)
       
   187         description = o.help
       
   188         if o.has_default:
       
   189             description = description + ' (%s)' % o.default
       
   190         return '%s %s' % (name, description)
       
   191 
       
   192 class ArgumentOption(Option):
       
   193 
       
   194     """ Option that takes an argument.
       
   195 
       
   196         An optional default argument can be given.
       
   197 
       
   198     """
       
   199     def __init__(self,name,help=None,default=None):
       
   200 
       
   201         # Basemethod
       
   202         Option.__init__(self,name,help)
       
   203 
       
   204         if default is not None:
       
   205             self.default = default
       
   206             self.has_default = 1
       
   207         self.takes_argument = 1
       
   208 
       
   209 class SwitchOption(Option):
       
   210 
       
   211     """ Options that can be on or off. Has an optional default value.
       
   212 
       
   213     """
       
   214     def __init__(self,name,help=None,default=None):
       
   215 
       
   216         # Basemethod
       
   217         Option.__init__(self,name,help)
       
   218 
       
   219         if default is not None:
       
   220             self.default = default
       
   221             self.has_default = 1
       
   222 
       
   223 ### Application baseclass
       
   224 
       
   225 class Application:
       
   226 
       
   227     """ Command line application interface with builtin argument
       
   228         parsing.
       
   229 
       
   230     """
       
   231     # Options the program accepts (Option instances)
       
   232     options = []
       
   233 
       
   234     # Standard settings; these are appended to options in __init__
       
   235     preset_options = [SwitchOption('-v',
       
   236                                    'generate verbose output'),
       
   237                       SwitchOption('-h',
       
   238                                    'show this help text'),
       
   239                       SwitchOption('--help',
       
   240                                    'show this help text'),
       
   241                       SwitchOption('--debug',
       
   242                                    'enable debugging'),
       
   243                       SwitchOption('--copyright',
       
   244                                    'show copyright'),
       
   245                       SwitchOption('--examples',
       
   246                                    'show examples of usage')]
       
   247 
       
   248     # The help layout looks like this:
       
   249     # [header]   - defaults to ''
       
   250     #
       
   251     # [synopsis] - formatted as '<self.name> %s' % self.synopsis
       
   252     #
       
   253     # options:
       
   254     # [options]  - formatted from self.options
       
   255     #
       
   256     # [version]  - formatted as 'Version:\n %s' % self.version, if given
       
   257     #
       
   258     # [about]    - defaults to ''
       
   259     #
       
   260     # Note: all fields that do not behave as template are formatted
       
   261     #       using the instances dictionary as substitution namespace,
       
   262     #       e.g. %(name)s will be replaced by the applications name.
       
   263     #
       
   264 
       
   265     # Header (default to program name)
       
   266     header = ''
       
   267 
       
   268     # Name (defaults to program name)
       
   269     name = ''
       
   270 
       
   271     # Synopsis (%(name)s is replaced by the program name)
       
   272     synopsis = '%(name)s [option] files...'
       
   273 
       
   274     # Version (optional)
       
   275     version = ''
       
   276 
       
   277     # General information printed after the possible options (optional)
       
   278     about = ''
       
   279 
       
   280     # Examples of usage to show when the --examples option is given (optional)
       
   281     examples = ''
       
   282 
       
   283     # Copyright to show
       
   284     copyright = __copyright__
       
   285 
       
   286     # Apply file globbing ?
       
   287     globbing = 1
       
   288 
       
   289     # Generate debug output ?
       
   290     debug = 0
       
   291 
       
   292     # Generate verbose output ?
       
   293     verbose = 0
       
   294 
       
   295     # Internal errors to catch
       
   296     InternalError = exceptions.Exception
       
   297 
       
   298     # Instance variables:
       
   299     values = None       # Dictionary of passed options (or default values)
       
   300                         # indexed by the options name, e.g. '-h'
       
   301     files = None        # List of passed filenames
       
   302     optionlist = None   # List of passed options
       
   303 
       
   304     def __init__(self,argv=None):
       
   305 
       
   306         # Setup application specs
       
   307         if argv is None:
       
   308             argv = sys.argv
       
   309         self.filename = os.path.split(argv[0])[1]
       
   310         if not self.name:
       
   311             self.name = os.path.split(self.filename)[1]
       
   312         else:
       
   313             self.name = self.name
       
   314         if not self.header:
       
   315             self.header = self.name
       
   316         else:
       
   317             self.header = self.header
       
   318 
       
   319         # Init .arguments list
       
   320         self.arguments = argv[1:]
       
   321 
       
   322         # Setup Option mapping
       
   323         self.option_map = option_dict(self.options)
       
   324 
       
   325         # Append preset options
       
   326         for option in self.preset_options:
       
   327             if not self.option_map.has_key(option.name):
       
   328                 self.add_option(option)
       
   329 
       
   330         # Init .files list
       
   331         self.files = []
       
   332 
       
   333         # Start Application
       
   334         try:
       
   335             # Process startup
       
   336             rc = self.startup()
       
   337             if rc is not None:
       
   338                 raise SystemExit,rc
       
   339 
       
   340             # Parse command line
       
   341             rc = self.parse()
       
   342             if rc is not None:
       
   343                 raise SystemExit,rc
       
   344 
       
   345             # Start application
       
   346             rc = self.main()
       
   347             if rc is None:
       
   348                 rc = 0
       
   349 
       
   350         except SystemExit,rc:
       
   351             pass
       
   352 
       
   353         except KeyboardInterrupt:
       
   354             print
       
   355             print '* User Break'
       
   356             print
       
   357             rc = 1
       
   358 
       
   359         except self.InternalError:
       
   360             print
       
   361             print '* Internal Error (use --debug to display the traceback)'
       
   362             if self.debug:
       
   363                 print
       
   364                 traceback.print_exc(20, sys.stdout)
       
   365             elif self.verbose:
       
   366                 print '  %s: %s' % sys.exc_info()[:2]
       
   367             print
       
   368             rc = 1
       
   369 
       
   370         raise SystemExit,rc
       
   371 
       
   372     def add_option(self, option):
       
   373 
       
   374         """ Add a new Option instance to the Application dynamically.
       
   375 
       
   376             Note that this has to be done *before* .parse() is being
       
   377             executed.
       
   378 
       
   379         """
       
   380         self.options.append(option)
       
   381         self.option_map[option.name] = option
       
   382 
       
   383     def startup(self):
       
   384 
       
   385         """ Set user defined instance variables.
       
   386 
       
   387             If this method returns anything other than None, the
       
   388             process is terminated with the return value as exit code.
       
   389 
       
   390         """
       
   391         return None
       
   392 
       
   393     def exit(self, rc=0):
       
   394 
       
   395         """ Exit the program.
       
   396 
       
   397             rc is used as exit code and passed back to the calling
       
   398             program. It defaults to 0 which usually means: OK.
       
   399 
       
   400         """
       
   401         raise SystemExit, rc
       
   402 
       
   403     def parse(self):
       
   404 
       
   405         """ Parse the command line and fill in self.values and self.files.
       
   406 
       
   407             After having parsed the options, the remaining command line
       
   408             arguments are interpreted as files and passed to .handle_files()
       
   409             for processing.
       
   410 
       
   411             As final step the option handlers are called in the order
       
   412             of the options given on the command line.
       
   413 
       
   414         """
       
   415         # Parse arguments
       
   416         self.values = values = {}
       
   417         for o in self.options:
       
   418             if o.has_default:
       
   419                 values[o.prefix+o.name] = o.default
       
   420             else:
       
   421                 values[o.prefix+o.name] = 0
       
   422         flags,lflags = _getopt_flags(self.options)
       
   423         try:
       
   424             optlist,files = getopt.getopt(self.arguments,flags,lflags)
       
   425             if self.globbing:
       
   426                 l = []
       
   427                 for f in files:
       
   428                     gf = glob.glob(f)
       
   429                     if not gf:
       
   430                         l.append(f)
       
   431                     else:
       
   432                         l[len(l):] = gf
       
   433                 files = l
       
   434             self.optionlist = optlist
       
   435             self.files = files + self.files
       
   436         except getopt.error,why:
       
   437             self.help(why)
       
   438             sys.exit(1)
       
   439 
       
   440         # Call file handler
       
   441         rc = self.handle_files(self.files)
       
   442         if rc is not None:
       
   443             sys.exit(rc)
       
   444 
       
   445         # Call option handlers
       
   446         for optionname, value in optlist:
       
   447 
       
   448             # Try to convert value to integer
       
   449             try:
       
   450                 value = string.atoi(value)
       
   451             except ValueError:
       
   452                 pass
       
   453 
       
   454             # Find handler and call it (or count the number of option
       
   455             # instances on the command line)
       
   456             handlername = 'handle' + string.replace(optionname, '-', '_')
       
   457             try:
       
   458                 handler = getattr(self, handlername)
       
   459             except AttributeError:
       
   460                 if value == '':
       
   461                     # count the number of occurances
       
   462                     if values.has_key(optionname):
       
   463                         values[optionname] = values[optionname] + 1
       
   464                     else:
       
   465                         values[optionname] = 1
       
   466                 else:
       
   467                     values[optionname] = value
       
   468             else:
       
   469                 rc = handler(value)
       
   470                 if rc is not None:
       
   471                     raise SystemExit, rc
       
   472 
       
   473         # Apply final file check (for backward compatibility)
       
   474         rc = self.check_files(self.files)
       
   475         if rc is not None:
       
   476             sys.exit(rc)
       
   477 
       
   478     def check_files(self,filelist):
       
   479 
       
   480         """ Apply some user defined checks on the files given in filelist.
       
   481 
       
   482             This may modify filelist in place. A typical application
       
   483             is checking that at least n files are given.
       
   484 
       
   485             If this method returns anything other than None, the
       
   486             process is terminated with the return value as exit code.
       
   487 
       
   488         """
       
   489         return None
       
   490 
       
   491     def help(self,note=''):
       
   492 
       
   493         self.print_header()
       
   494         if self.synopsis:
       
   495             print 'Synopsis:'
       
   496             # To remain backward compatible:
       
   497             try:
       
   498                 synopsis = self.synopsis % self.name
       
   499             except (NameError, KeyError, TypeError):
       
   500                 synopsis = self.synopsis % self.__dict__
       
   501             print ' ' + synopsis
       
   502         print
       
   503         self.print_options()
       
   504         if self.version:
       
   505             print 'Version:'
       
   506             print ' %s' % self.version
       
   507             print
       
   508         if self.about:
       
   509             print string.strip(self.about % self.__dict__)
       
   510             print
       
   511         if note:
       
   512             print '-'*72
       
   513             print 'Note:',note
       
   514             print
       
   515 
       
   516     def notice(self,note):
       
   517 
       
   518         print '-'*72
       
   519         print 'Note:',note
       
   520         print '-'*72
       
   521         print
       
   522 
       
   523     def print_header(self):
       
   524 
       
   525         print '-'*72
       
   526         print self.header % self.__dict__
       
   527         print '-'*72
       
   528         print
       
   529 
       
   530     def print_options(self):
       
   531 
       
   532         options = self.options
       
   533         print 'Options and default settings:'
       
   534         if not options:
       
   535             print '  None'
       
   536             return
       
   537         long = filter(lambda x: x.prefix == '--', options)
       
   538         short = filter(lambda x: x.prefix == '-', options)
       
   539         items = short + long
       
   540         for o in options:
       
   541             print ' ',o
       
   542         print
       
   543 
       
   544     #
       
   545     # Example handlers:
       
   546     #
       
   547     # If a handler returns anything other than None, processing stops
       
   548     # and the return value is passed to sys.exit() as argument.
       
   549     #
       
   550 
       
   551     # File handler
       
   552     def handle_files(self,files):
       
   553 
       
   554         """ This may process the files list in place.
       
   555         """
       
   556         return None
       
   557 
       
   558     # Short option handler
       
   559     def handle_h(self,arg):
       
   560 
       
   561         self.help()
       
   562         return 0
       
   563 
       
   564     def handle_v(self, value):
       
   565 
       
   566         """ Turn on verbose output.
       
   567         """
       
   568         self.verbose = 1
       
   569 
       
   570     # Handlers for long options have two underscores in their name
       
   571     def handle__help(self,arg):
       
   572 
       
   573         self.help()
       
   574         return 0
       
   575 
       
   576     def handle__debug(self,arg):
       
   577 
       
   578         self.debug = 1
       
   579         # We don't want to catch internal errors:
       
   580         self.InternalError = None
       
   581 
       
   582     def handle__copyright(self,arg):
       
   583 
       
   584         self.print_header()
       
   585         print string.strip(self.copyright % self.__dict__)
       
   586         print
       
   587         return 0
       
   588 
       
   589     def handle__examples(self,arg):
       
   590 
       
   591         self.print_header()
       
   592         if self.examples:
       
   593             print 'Examples:'
       
   594             print
       
   595             print string.strip(self.examples % self.__dict__)
       
   596             print
       
   597         else:
       
   598             print 'No examples available.'
       
   599             print
       
   600         return 0
       
   601 
       
   602     def main(self):
       
   603 
       
   604         """ Override this method as program entry point.
       
   605 
       
   606             The return value is passed to sys.exit() as argument.  If
       
   607             it is None, 0 is assumed (meaning OK). Unhandled
       
   608             exceptions are reported with exit status code 1 (see
       
   609             __init__ for further details).
       
   610 
       
   611         """
       
   612         return None
       
   613 
       
   614 # Alias
       
   615 CommandLine = Application
       
   616 
       
   617 def _test():
       
   618 
       
   619     class MyApplication(Application):
       
   620         header = 'Test Application'
       
   621         version = __version__
       
   622         options = [Option('-v','verbose')]
       
   623 
       
   624         def handle_v(self,arg):
       
   625             print 'VERBOSE, Yeah !'
       
   626 
       
   627     cmd = MyApplication()
       
   628     if not cmd.values['-h']:
       
   629         cmd.help()
       
   630     print 'files:',cmd.files
       
   631     print 'Bye...'
       
   632 
       
   633 if __name__ == '__main__':
       
   634     _test()