summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnthon van der Neut <anthon@mnt.org>2014-03-26 20:19:39 +0100
committerAnthon van der Neut <anthon@mnt.org>2014-03-26 20:19:39 +0100
commit6198e7e496bc4c840f2a75a973b6a852a2484389 (patch)
treeae5cf84d24d18093fc8841210abcd88524209ea4
parentb54bc003810027481e8125be28af7af0781dadcc (diff)
downloadruamel.std.argparse-6198e7e496bc4c840f2a75a973b6a852a2484389.tar.gz
initial ProgramBase
-rw-r--r--__init__.py177
-rw-r--r--test/test_program.py41
2 files changed, 201 insertions, 17 deletions
diff --git a/__init__.py b/__init__.py
index 8bc424f..b69c8ca 100644
--- a/__init__.py
+++ b/__init__.py
@@ -60,6 +60,7 @@ class SubParsersAction(argparse._SubParsersAction):
return parser
+
from _action.checksinglestore import CheckSingleStoreAction
from _action.count import CountAction
from _action.splitappend import SplitAppendAction
@@ -81,9 +82,8 @@ class SmartFormatter(argparse.HelpFormatter):
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
+ # print 'TEXT', text
if text.startswith('D|'):
self._add_defaults = True
text = text[2:]
@@ -106,7 +106,7 @@ class SmartFormatter(argparse.HelpFormatter):
# decorators
# decorate method as a subparser, ToDo: signature
-def sub_parser(*args, **kw):
+def sub_parser1(*args, **kw):
class Decorator(object):
def __init__(self):
self.target = None
@@ -134,7 +134,7 @@ def sub_parser(*args, **kw):
"""called with the original function that is decorated
add function name to last options element
"""
- self.target.options[-1]['fun'] = args[0].__name__
+ self.target.options[-1]['fun'] = args[0].__name__
pass
if not hasattr(self.target, "options"):
@@ -146,7 +146,7 @@ def sub_parser(*args, **kw):
# global options can come before and after a sub_parser, ToDo: signature
-def global_option(*args, **kw):
+def global_option1(*args, **kw):
def decorator(target):
target.global_option = {'args': args, 'kw': kw}
return target
@@ -154,14 +154,14 @@ def global_option(*args, **kw):
# global only options can come before a sub_parser only, ToDo: signature
-def global_only_option(*args, **kw):
+def global_only_option1(*args, **kw):
def decorator(target):
target.global_only_option = {'args': args, 'kw': kw}
return target
return decorator
-def create_argument_parser(self, *args, **keywords):
+def create_argument_parser1(self, *args, **keywords):
argument_parser = argparse.ArgumentParser(**keywords)
self._subparsers = None
for x in dir(self):
@@ -171,8 +171,8 @@ def create_argument_parser(self, *args, **keywords):
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)
+ dest="subparser_level_0", 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)
@@ -181,10 +181,10 @@ def create_argument_parser(self, *args, **keywords):
**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
+ # 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:
@@ -201,13 +201,19 @@ def create_argument_parser(self, *args, **keywords):
else:
# add long option based on function name
arg.insert(0, '--' + fun_name)
- #print 'arg2', arg
+ # print 'arg2', arg
sp.add_argument(*arg, **o['kw'])
- #print ' opt:', x, method.options
+ # 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)
+ if not arg or not arg[0].startswith('--'):
+ arg = list(arg)
+ arg.insert(0, '--' + x)
+ try:
+ argument_parser.add_argument(*arg, **kw)
+ except TypeError:
+ print('args, kw', arg, kw)
for x in dir(self):
if x.startswith('_'):
continue
@@ -216,9 +222,146 @@ def create_argument_parser(self, *args, **keywords):
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('--'):
+ if not arg or not arg[0].startswith('--'):
arg = list(arg)
arg.insert(0, '--' + x)
sp.add_argument(*arg, **method.global_option['kw'])
return argument_parser
+
+class ProgramBase(object):
+ def __init__(self, *args, **kw):
+ self._verbose = kw.pop('verbose', 0)
+ self._parser = argparse.ArgumentParser(*args, **kw)
+ cls = self
+ self._subparsers = None
+ for x in dir(cls):
+ if x.startswith('_'):
+ continue
+ method = getattr(self, x)
+ if hasattr(method, "_sub_parser"):
+ if self._subparsers is None:
+ self._subparsers = self._parser.add_subparsers(
+ dest="subparser_level_0", 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
+ for o in method._sub_parser['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 False:
+ if hasattr(method, "global_only_option"):
+ arg = method.global_only_option['args']
+ kw = method.global_only_option['kw']
+ if not arg or not arg[0].startswith('--'):
+ arg = list(arg)
+ arg.insert(0, '--' + x)
+ try:
+ self._parser.add_argument(*arg, **kw)
+ except TypeError:
+ print('args, kw', arg, kw)
+ for x in dir(self):
+ if x.startswith('_') and not x == '__init__':
+ continue
+ method = getattr(self, x)
+ if hasattr(method, "_options"): # not transfered to sub_parser
+ for o in method._options:
+ arg = o['args']
+ kw = o['kw']
+ global_option = kw.pop('global_option', False)
+ try:
+ self._parser.add_argument(*arg, **kw)
+ except TypeError:
+ print('args, kw', arg, kw)
+ if global_option:
+ for name in self._subparsers._name_parser_map:
+ sp = self._subparsers._name_parser_map[name]
+ sp.add_argument(*arg, **kw)
+
+ def _parse_args(self, *args):
+ self._args = self._parser.parse_args(*args)
+ return self._args
+
+ @staticmethod
+ def option(*args, **kw):
+ def decorator(target):
+ if not hasattr(target, '_options'):
+ target._options = []
+ # insert to reverse order of list
+ target._options.insert(0, {'args': args, 'kw': kw})
+ return target
+ return decorator
+
+ @staticmethod
+ def sub_parser(*args, **kw):
+ class Decorator(object):
+ def __init__(self):
+ self.target = None
+
+ def __call__(self, target):
+ self.target = target
+ # move options to sub_parser
+ o = getattr(target, '_options', [])
+ if o:
+ del target._options
+ target._sub_parser = {'args': args, 'kw': kw, 'options': o}
+ return target
+
+ def XXXoption(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
+
+
+def option(*args, **kw):
+ return ProgramBase.option(*args, **kw)
+
+def sub_parser(*args, **kw):
+ return ProgramBase.sub_parser(*args, **kw) \ No newline at end of file
diff --git a/test/test_program.py b/test/test_program.py
new file mode 100644
index 0000000..719e653
--- /dev/null
+++ b/test/test_program.py
@@ -0,0 +1,41 @@
+
+import pytest
+
+from ruamel.std.argparse import ProgramBase, option, sub_parser
+
+class Program(ProgramBase):
+ @option('--verbose', global_option=True, action='store_true')
+ @option('--quiet', action='store_true')
+ def __init__(self):
+ ProgramBase.__init__(self)
+
+ @sub_parser(help="call mercurial")
+ @option('--show', action='store_true')
+ @option('--no-show', help='do not show', metavar='NSHO')
+ @option('file-name', nargs='*')
+ def hg(self):
+ pass
+
+ #@hg.sub_parser()
+ #def check(self):
+ # pass
+
+ @sub_parser(help="call git")
+ def git(self):
+ pass
+
+
+def test_program(capsys):
+ print '------------- hallo'
+ p = Program()
+
+ with pytest.raises(SystemExit):
+ p._parse_args('-h'.split())
+ out, err = capsys.readouterr()
+ print out
+ print '++++++++++++++'
+ with pytest.raises(SystemExit):
+ p._parse_args('hg -h'.split())
+ out, err = capsys.readouterr()
+ print out
+ assert False \ No newline at end of file