113 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			Python
		
	
	
	
			
		
		
	
	
			113 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			Python
		
	
	
	
| """
 | |
| thin wrapper around Python's optparse.py
 | |
| adding some extra checks and ways to systematically
 | |
| have Environment variables provide default values
 | |
| for options.  basic usage:
 | |
| 
 | |
|    >>> parser = Parser()
 | |
|    >>> parser.addoption("--hello", action="store_true", dest="hello")
 | |
|    >>> option, args = parser.parse(['--hello'])
 | |
|    >>> option.hello
 | |
|    True
 | |
|    >>> args
 | |
|    []
 | |
| 
 | |
| """
 | |
| import py
 | |
| import optparse
 | |
| 
 | |
| class Parser:
 | |
|     """ Parser for command line arguments. """
 | |
| 
 | |
|     def __init__(self, usage=None, processopt=None):
 | |
|         self._anonymous = OptionGroup("custom options", parser=self)
 | |
|         self._groups = []
 | |
|         self._processopt = processopt
 | |
|         self._usage = usage
 | |
|         self.hints = []
 | |
| 
 | |
|     def processoption(self, option):
 | |
|         if self._processopt:
 | |
|             if option.dest:
 | |
|                 self._processopt(option)
 | |
| 
 | |
|     def addnote(self, note):
 | |
|         self._notes.append(note)
 | |
| 
 | |
|     def getgroup(self, name, description="", after=None):
 | |
|         for group in self._groups:
 | |
|             if group.name == name:
 | |
|                 return group
 | |
|         group = OptionGroup(name, description, parser=self)
 | |
|         i = 0
 | |
|         for i, grp in enumerate(self._groups):
 | |
|             if grp.name == after:
 | |
|                 break
 | |
|         self._groups.insert(i+1, group)
 | |
|         return group
 | |
| 
 | |
|     addgroup = getgroup
 | |
|     def addgroup(self, name, description=""):
 | |
|         py.log._apiwarn("1.1", "use getgroup() which gets-or-creates")
 | |
|         return self.getgroup(name, description)
 | |
| 
 | |
|     def addoption(self, *opts, **attrs):
 | |
|         """ add an optparse-style option. """
 | |
|         self._anonymous.addoption(*opts, **attrs)
 | |
| 
 | |
|     def parse(self, args):
 | |
|         optparser = MyOptionParser(self)
 | |
|         groups = self._groups + [self._anonymous]
 | |
|         for group in groups:
 | |
|             if group.options:
 | |
|                 desc = group.description or group.name
 | |
|                 optgroup = optparse.OptionGroup(optparser, desc)
 | |
|                 optgroup.add_options(group.options)
 | |
|                 optparser.add_option_group(optgroup)
 | |
|         return optparser.parse_args([str(x) for x in args])
 | |
| 
 | |
|     def parse_setoption(self, args, option):
 | |
|         parsedoption, args = self.parse(args)
 | |
|         for name, value in parsedoption.__dict__.items():
 | |
|             setattr(option, name, value)
 | |
|         return args
 | |
| 
 | |
| 
 | |
| class OptionGroup:
 | |
|     def __init__(self, name, description="", parser=None):
 | |
|         self.name = name
 | |
|         self.description = description
 | |
|         self.options = []
 | |
|         self.parser = parser
 | |
| 
 | |
|     def addoption(self, *optnames, **attrs):
 | |
|         """ add an option to this group. """
 | |
|         option = optparse.Option(*optnames, **attrs)
 | |
|         self._addoption_instance(option, shortupper=False)
 | |
| 
 | |
|     def _addoption(self, *optnames, **attrs):
 | |
|         option = optparse.Option(*optnames, **attrs)
 | |
|         self._addoption_instance(option, shortupper=True)
 | |
| 
 | |
|     def _addoption_instance(self, option, shortupper=False):
 | |
|         if not shortupper:
 | |
|             for opt in option._short_opts:
 | |
|                 if opt[0] == '-' and opt[1].islower():
 | |
|                     raise ValueError("lowercase shortoptions reserved")
 | |
|         if self.parser:
 | |
|             self.parser.processoption(option)
 | |
|         self.options.append(option)
 | |
| 
 | |
| 
 | |
| class MyOptionParser(optparse.OptionParser):
 | |
|     def __init__(self, parser):
 | |
|         self._parser = parser
 | |
|         optparse.OptionParser.__init__(self, usage=parser._usage)
 | |
|     def format_epilog(self, formatter):
 | |
|         hints = self._parser.hints
 | |
|         if hints:
 | |
|             s = "\n".join(["hint: " + x for x in hints]) + "\n"
 | |
|             s = "\n" + s + "\n"
 | |
|             return s
 | |
|         return ""
 |