# coding: utf-8 # < from ruamel.util.new import _convert_version def _convert_version(tup): """create a PEP 386 pseudo-format conformant string from tuple tup""" ret_val = str(tup[0]) # first is always digit next_sep = "." # separator for next extension, can be "" or "." for x in tup[1:]: if isinstance(x, int): ret_val += next_sep + str(x) next_sep = '.' continue first_letter = x[0].lower() next_sep = '' if first_letter in 'abcr': ret_val += 'rc' if first_letter == 'r' else first_letter elif first_letter in 'pd': ret_val += '.post' if first_letter == 'p' else '.dev' return ret_val # < version_info = (0, 2, "alpha", 2) __version__ = _convert_version(version_info) del _convert_version import argparse from argparse import ArgumentParser class SubParsersAction(argparse._SubParsersAction): """support aliases, based on differences of 3.3 and 2.7 """ class _AliasesChoicesPseudoAction(argparse.Action): def __init__(self, name, aliases, help): metavar = dest = name if aliases: metavar += ' (%s)' % ', '.join(aliases) sup = super(SubParsersAction._AliasesChoicesPseudoAction, self) sup.__init__(option_strings=[], dest=dest, help=help, metavar=metavar) def add_parser(self, name, **kwargs): # remove aliases and help kwargs so the orginal add_parser # does not get them aliases = kwargs.pop('aliases', ()) help = kwargs.pop('help', None) parser = argparse._SubParsersAction.add_parser(self, name, **kwargs) if help is not None: choice_action = self._AliasesChoicesPseudoAction(name, aliases, help) self._choices_actions.append(choice_action) if aliases is not None: for alias in aliases: self._name_parser_map[alias] = parser return parser from _action.checksinglestore import CheckSingleStoreAction from _action.count import CountAction from _action.splitappend import SplitAppendAction class SmartFormatter(argparse.HelpFormatter): """ you can only specify one formatter in standard argparse, so you cannot both have pre-formatted description (RawDescriptionHelpFormatter) and ArgumentDefaultsHelpFormatter. The SmartFormatter has sensible defaults (RawDescriptionFormatter) and the individual help text can be marked ( help="R|" ) for variations in formatting. """ def __init__(self, *args, **kw): self._add_defaults = False super(SmartFormatter, self).__init__(*args, **kw) def _fill_text(self, text, width, indent): return ''.join([indent + line for line in text.splitlines(True)]) def _split_lines(self, text, width): #print 'TEXT', text if text.startswith('D|'): self._add_defaults = True text = text[2:] if text.startswith('R|'): return text[2:].splitlines() return argparse.HelpFormatter._split_lines(self, text, width) def _get_help_string(self, action): if not self._add_defaults: return argparse.HelpFormatter._get_help_string(self, action) help = action.help if '%(default)' not in action.help: if action.default is not argparse.SUPPRESS: defaulting_nargs = [argparse.OPTIONAL, argparse.ZERO_OR_MORE] if action.option_strings or action.nargs in defaulting_nargs: help += ' (default: %(default)s)' return help # decorators # decorate method as a subparser, ToDo: signature def sub_parser(*args, **kw): class Decorator(object): def __init__(self): self.target = None def __call__(self, target): self.target = target target.sub_parser = {'args': args, 'kw': kw} target.option = self.option return target def option(self, *a, **k): """ after a method xyz is decorated as sub_parser, you can add options with: @xyz.option('--force') def force(self): pass if option argument is a short option ('-F'), add the long option based on the function name if no option argument, add function_name if 'nargs' in k else add long option based on function name """ # here check if a is option name else take from function def option_func(*args): """called with the original function that is decorated add function name to last options element """ self.target.options[-1]['fun'] = args[0].__name__ pass if not hasattr(self.target, "options"): self.target.options = [] self.target.options.append({'args': a, 'kw': k}) return option_func decorator = Decorator() return decorator # global options can come before and after a sub_parser, ToDo: signature def global_option(*args, **kw): def decorator(target): target.global_option = {'args': args, 'kw': kw} return target return decorator # global only options can come before a sub_parser only, ToDo: signature def global_only_option(*args, **kw): def decorator(target): target.global_only_option = {'args': args, 'kw': kw} return target return decorator def create_argument_parser(self, *args, **keywords): argument_parser = argparse.ArgumentParser(**keywords) self._subparsers = None for x in dir(self): if x.startswith('_'): continue method = getattr(self, x) if hasattr(method, "sub_parser"): if self._subparsers is None: self._subparsers = argument_parser.add_subparsers( dest="subparser_name", help='sub-command help') #(name, aliases=aliases, help=help) arg = method.sub_parser['args'] if not arg or not isinstance(arg[0], basestring): arg = list(arg) arg.insert(0, x) sp = self._subparsers.add_parser(*arg, **method.sub_parser['kw']) sp.set_defaults(func=method) #print x, method.sub_parser if hasattr(method, "options"): for o in method.options: #print 'arg1', o arg = list(o['args']) fun_name = o.get('fun') if arg: # short option name only, add long option name # based on function name if len(arg[0]) == 2 and arg[0][0] == '-': if (fun_name): arg.insert(0, '--' + fun_name) else: # no option name if o['kw'].get('nargs') == '+': # file names etc, no leading dashes arg.insert(0, fun_name) else: # add long option based on function name arg.insert(0, '--' + fun_name) #print 'arg2', arg sp.add_argument(*arg, **o['kw']) #print ' opt:', x, method.options if hasattr(method, "global_only_option"): arg = method.global_only_option['args'] kw = method.global_only_option['kw'] argument_parser.add_argument(*arg, **kw) for x in dir(self): if x.startswith('_'): continue method = getattr(self, x) if hasattr(method, "global_option"): for name in self._subparsers._name_parser_map: sp = self._subparsers._name_parser_map[name] arg = method.global_option['args'] if arg and not arg[0].startswith('--'): arg = list(arg) arg.insert(0, '--' + x) sp.add_argument(*arg, **method.global_option['kw']) return argument_parser