Tryag File Manager
Home
-
Turbo Force
Current Path :
/
usr
/
lib
/
python2.4
/
site-packages
/
mx
/
Misc
/
Upload File :
New :
File
Dir
//usr/lib/python2.4/site-packages/mx/Misc/CommandLine.py
#-*- coding: latin-1 -*- """ CommandLine - Get and parse command line options NOTE: This still is very much work in progress !!! Different version are likely to be incompatible. TODO: · Incorporate the changes made by (see Inbox) · Add number range option using srange() Copyright (c) 1997-2001, Marc-Andre Lemburg; mailto:mal@lemburg.com Copyright (c) 2000-2001, eGenix.com Software GmbH; mailto:info@egenix.com See the documentation for further information on copyrights, or contact the author. All Rights Reserved. """ __version__ = '1.0' import sys,getopt,string,glob,os,traceback,re ### Helpers def _getopt_flags(options): """ Convert the option list to a getopt flag string and long opt list """ s = [] l = [] for o in options: if o.prefix == '-': # short option s.append(o.name) if o.takes_argument: s.append(':') else: # long option if o.takes_argument: l.append(o.name+'=') else: l.append(o.name) return string.join(s,''),l def invisible_input(prompt='>>> '): """ Get raw input from a terminal without echoing the characters to the terminal, e.g. for password queries. """ import getpass entry = getpass.getpass(prompt) if entry is None: raise KeyboardInterrupt return entry def option_dict(options): """ Return a dictionary mapping option names to Option instances. """ d = {} for option in options: d[option.name] = option return d # Alias getpasswd = invisible_input _integerRE = re.compile('\s*(-?\d+)\s*$') _integerRangeRE = re.compile('\s*(-?\d+)\s*-\s*(-?\d+)\s*$') def srange(s, split=string.split,integer=_integerRE, integerRange=_integerRangeRE): """ Converts a textual representation of integer numbers and ranges to a Python list. Supported formats: 2,3,4,2-10,-1 - -3, 5 - -2 Values are appended to the created list in the order specified in the string. """ l = [] append = l.append for entry in split(s,','): m = integer.match(entry) if m: append(int(m.groups()[0])) continue m = integerRange.match(entry) if m: start,end = map(int,m.groups()) l[len(l):] = range(start,end+1) return l def abspath(path, expandvars=os.path.expandvars,expanduser=os.path.expanduser, join=os.path.join,getcwd=os.getcwd): """ Return the corresponding absolute path for path. path is expanded in the usual shell ways before joining it with the current working directory. """ try: path = expandvars(path) except AttributeError: pass try: path = expanduser(path) except AttributeError: pass return join(getcwd(), path) ### Option classes class Option: """ Option base class. Takes no argument. """ default = None helptext = '' prefix = '-' takes_argument = 0 has_default = 0 tab = 15 def __init__(self,name,help=None): if not name[:1] == '-': raise TypeError,'option names must start with "-"' if name[1:2] == '-': self.prefix = '--' self.name = name[2:] else: self.name = name[1:] if help: self.help = help def __str__(self): o = self name = o.prefix + o.name if o.takes_argument: name = name + ' arg' if len(name) > self.tab: name = name + '\n' + ' ' * (self.tab + 1 + len(o.prefix)) else: name = '%-*s ' % (self.tab, name) description = o.help if o.has_default: description = description + ' (%s)' % o.default return '%s %s' % (name, description) class ArgumentOption(Option): """ Option that takes an argument. An optional default argument can be given. """ def __init__(self,name,help=None,default=None): # Basemethod Option.__init__(self,name,help) if default is not None: self.default = default self.has_default = 1 self.takes_argument = 1 class SwitchOption(Option): """ Options that can be on or off. Has an optional default value. """ def __init__(self,name,help=None,default=None): # Basemethod Option.__init__(self,name,help) if default is not None: self.default = default self.has_default = 1 ### Application baseclass class Application: """ Command line application interface with builtin argument parsing. """ # Options the program accepts (Option instances) options = [] # Standard settings; these are appended to options in __init__ preset_options = [SwitchOption('-v','generate verbose output'), SwitchOption('-h','show this help text'), SwitchOption('--help','show this help text'), SwitchOption('--debug','enable debugging'), SwitchOption('--copyright','show copyright'), SwitchOption('--examples','show examples of usage')] # The help layout looks like this: # [header] - defaults to '' # # [synopsis] - formatted as '<self.name> %s' % self.synopsis # # options: # [options] - formatted from self.options # # [version] - formatted as 'Version:\n %s' % self.version, if given # # [about] - defaults to '' # # Note: all fields that do not behave as template are formatted # using the instances dictionary as substitution namespace, # e.g. %(name)s will be replaced by the applications name. # # Header (default to program name) header = '' # Name (defaults to program name) name = '' # Synopsis (%(name)s is replaced by the program name) synopsis = '%(name)s [option] files...' # Version (optional) version = '' # General information printed after the possible options (optional) about = '' # Examples of usage to show when the --examples option is given (optional) examples = '' # Copyright to show copyright = ( 'Copyright (c) 1997-2001, Marc-Andre Lemburg; mailto:mal@lemburg.com\n' 'Copyright (c) 2000-2001, eGenix.com Software GmbH; mailto:info@egenix.com\n' 'See the documentation for further information on copyrights,\n' 'or contact the author. All Rights Reserved.\n' '*** UNAUTHORIZED COPYING, USAGE or DISTRIBUTION PROHIBITED. ***' ) # Apply file globbing ? globbing = 1 # Generate debug output ? debug = 0 # Generate verbose output ? verbose = 0 # Instance variables: values = None # Dictionary of passed options (or default values) # indexed by the options name, e.g. '-h' files = None # List of passed filenames def __init__(self,argv=None): # Setup application specs if argv is None: argv = sys.argv self.filename = os.path.split(argv[0])[1] if not self.name: self.name = os.path.split(self.filename)[1] else: self.name = self.name if not self.header: self.header = self.name else: self.header = self.header # Init .arguments list self.arguments = argv[1:] # Setup Option mapping self.option_map = option_dict(self.options) # Append preset options for option in self.preset_options: if not self.option_map.has_key(option.name): self.add_option(option) # Init .files list self.files = [] # Start Application try: # Process startup rc = self.startup() if rc is not None: raise SystemExit,rc # Parse command line rc = self.parse() if rc is not None: raise SystemExit,rc # Start application rc = self.main() if rc is None: rc = 0 except SystemExit,rc: pass except KeyboardInterrupt: print print '* User Break' rc = 1 except: print print '* Internal Error' if self.debug: print traceback.print_exc(20) rc = 1 raise SystemExit,rc def add_option(self, option): """ Add a new Option instance to the Application dynamically. Note that this has to be done *before* .parse() is being executed. """ self.options.append(option) self.option_map[option.name] = option def startup(self): """ Set user defined instance variables. If this method returns anything other than None, the process is terminated with the return value as exit code. """ return None def exit(self, rc=0): """ Exit the program. rc is used as exit code and passed back to the calling program. It defaults to 0 which usually means: OK. """ raise SystemExit, rc def parse(self): """ Parse the command line and fill in self.values and self.files. After having parsed the options, the remaining command line arguments are interpreted as files and passed to .handle_files() for processing. As final step the option handlers are called in the order of the options given on the command line. """ # Parse arguments self.values = values = {} for o in self.options: if o.has_default: values[o.prefix+o.name] = o.default else: values[o.prefix+o.name] = 0 flags,lflags = _getopt_flags(self.options) try: optlist,files = getopt.getopt(self.arguments,flags,lflags) if self.globbing: l = [] for f in files: gf = glob.glob(f) if not gf: l.append(f) else: l[len(l):] = gf files = l self.optionlist = optlist self.files = files + self.files except getopt.error,why: self.help(why) sys.exit(1) # Call file handler rc = self.handle_files(self.files) if rc is not None: sys.exit(rc) # Call option handlers for optionname, value in optlist: # Try to convert value to integer try: value = string.atoi(value) except ValueError: pass # Find handler and call it (or count the number of option # instances on the command line) handlername = 'handle' + string.replace(optionname, '-', '_') try: handler = getattr(self, handlername) except AttributeError: if value == '': # count the number of occurances if values.has_key(optionname): values[optionname] = values[optionname] + 1 else: values[optionname] = 1 else: values[optionname] = value else: rc = handler(value) if rc is not None: raise SystemExit, rc # Apply final file check (for backward compatibility) rc = self.check_files(self.files) if rc is not None: sys.exit(rc) def check_files(self,filelist): """ Apply some user defined checks on the files given in filelist. This may modify filelist in place. A typical application is checking that at least n files are given. If this method returns anything other than None, the process is terminated with the return value as exit code. """ return None def help(self,note=''): self.print_header() if self.synopsis: print 'Synopsis:' # To remain backward compatible: try: synopsis = self.synopsis % self.name except (NameError, KeyError, TypeError): synopsis = self.synopsis % self.__dict__ print ' ' + synopsis print self.print_options() if self.version: print 'Version:' print ' %s' % self.version print if self.about: print string.strip(self.about % self.__dict__) print if note: print '-'*72 print 'Note:',note print def notice(self,note): print '-'*72 print 'Note:',note print '-'*72 print def print_header(self): print '-'*72 print self.header % self.__dict__ print '-'*72 print def print_options(self): options = self.options print 'Options and default settings:' if not options: print ' None' return long = filter(lambda x: x.prefix == '--', options) short = filter(lambda x: x.prefix == '-', options) items = short + long for o in options: print ' ',o print # # Example handlers: # # If a handler returns anything other than None, processing stops # and the return value is passed to sys.exit() as argument. # # File handler def handle_files(self,files): """ This may process the files list in place. """ return None # Short option handler def handle_h(self,arg): self.help() return 0 def handle_v(self, value): """ Turn on verbose output. """ self.verbose = 1 # Handlers for long options have two underscores in their name def handle__help(self,arg): self.help() return 0 def handle__debug(self,arg): self.debug = 1 def handle__copyright(self,arg): self.print_header() print string.strip(self.copyright % self.__dict__) print return 0 def handle__examples(self,arg): self.print_header() if self.examples: print 'Examples:' print print string.strip(self.examples % self.__dict__) print else: print 'No examples available.' print return 0 def main(self): """ Override this method as program entry point. The return value is passed to sys.exit() as argument. If it is None, 0 is assumed (meaning OK). Unhandled exceptions are reported with exit status code 1 (see __init__ for further details). """ return None # Alias CommandLine = Application def _test(): class MyApplication(Application): header = 'Test Application' version = __version__ options = [Option('-v','verbose')] def handle_v(self,arg): print 'VERBOSE, Yeah !' cmd = MyApplication() if not cmd.values['-h']: cmd.help() print 'files:',cmd.files print 'Bye...' if __name__ == '__main__': _test()