summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnthon van der Neut <anthon@mnt.org>2014-03-17 10:18:36 +0100
committerAnthon van der Neut <anthon@mnt.org>2014-03-17 10:18:36 +0100
commit677f099cdbbf5d4e313640bf47358fe77ffcf880 (patch)
tree4b9999e7beb4dbef76a600348257d5ffc258de9e
parente98fae6e8f96464dad291dea62887f6d9db2657a (diff)
downloadruamel.std.argparse-677f099cdbbf5d4e313640bf47358fe77ffcf880.tar.gz
added sub_parser, global_option, global_only_option, create_argument_parser
These can be inserted into and update by using ruamel_util_updateprogram
-rw-r--r--__init__.py120
1 files changed, 120 insertions, 0 deletions
diff --git a/__init__.py b/__init__.py
index 0796ac7..eef0950 100644
--- a/__init__.py
+++ b/__init__.py
@@ -98,3 +98,123 @@ class SmartFormatter(argparse.HelpFormatter):
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, kw = method.global_only_option
+ 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
+