diff options
author | Anthon van der Neut <anthon@mnt.org> | 2014-10-15 10:50:11 +0200 |
---|---|---|
committer | Anthon van der Neut <anthon@mnt.org> | 2014-10-15 10:50:11 +0200 |
commit | 937fd83a0cf7fc443843a09ac05759c6a3ec6d1c (patch) | |
tree | 3fb9aae7114ec5a821ce4952f011cfad9f428d13 | |
parent | 4b51266bb19f7df8c8708485ea97869327d87a06 (diff) | |
download | ruamel.std.argparse-937fd83a0cf7fc443843a09ac05759c6a3ec6d1c.tar.gz |
Added set_default_subparser code as extra method for ArgumentParser.
Added keyword default_sub_parser to ProgramBase._parse_args()
-rw-r--r-- | Makefile | 26 | ||||
-rw-r--r-- | __init__.py | 112 | ||||
-rw-r--r-- | tox.ini | 2 |
3 files changed, 90 insertions, 50 deletions
@@ -2,34 +2,14 @@ UTILNAME:=argparse PKGNAME:=ruamel.std.argparse VERSION:=$$(python setup.py --version) -DIST:=dist/$(PKGNAME)-$(VERSION).tar.gz -REGEN:=/usr/local/bin/ruamel_util_new util --std argparse --skip-util --skip-hg +REGEN:=/usr/local/bin/ruamel_util_new util --std Argparse --skip-util --skip-hg -sdist: - python setup.py sdist - -wheel: - python setup.py bdist_wheel +include ~/.config/ruamel_util_new/Makefile.inc clean: - rm -rf build .tox $(PKGNAME).egg-info/ + rm -rf build .tox $(PKGNAME).egg-info/ README.pdf find . -name "*.pyc" -exec rm {} + -tar: - tar tf $(DIST) - -devpi: - devpi upload $(DIST) - -regen_setup: - rm -f ../argparse/setup.py - $(REGEN) - pep8 setup.py - -regen_makefile: - rm -f ../$(UTILNAME)/Makefile - $(REGEN) - BBASE:=ssh://hg@bitbucket.org/ruamel BB:=$(BBASE)/std.$$(/usr/bin/basename $$PWD) diff --git a/__init__.py b/__init__.py index 06e9803..4d551d3 100644 --- a/__init__.py +++ b/__init__.py @@ -11,6 +11,7 @@ if PY3: else: string_types = basestring, + # < from ruamel.util.new import _convert_version def _convert_version(tup): """create a PEP 386 pseudo-format conformant string from tuple tup""" @@ -42,6 +43,10 @@ from argparse import ArgumentParser class SubParsersAction(argparse._SubParsersAction): """support aliases, based on differences of 3.3 and 2.7 + + install with: + if sys.version_info < (3,): # add aliases support + self._argparser.register('action', 'parsers', SubParsersAction) """ class _AliasesChoicesPseudoAction(argparse.Action): @@ -137,14 +142,24 @@ class ProgramBase(object): ToDo: - grouping - mutual exclusion + Done: - Original order/sorted (by kw) + - aliases """ _methods_with_sub_parsers = [] def __init__(self, *args, **kw): + """ + the 'aliases' keyword does result in the 'aliases' keyword in + @sub_parser (as for Py3 in add_parser()) being available for 2.x + """ self._verbose = kw.pop('verbose', 0) + aliases = kw.pop('aliases', 0) self._parser = argparse.ArgumentParser(*args, **kw) + if aliases and sys.version_info < (3,): + self._parser.register('action', 'parsers', SubParsersAction) + self._program_base_initialising = True cls = self self._sub_parsers = None methods_with_sub_parsers = [] # list to process, multilevel @@ -156,7 +171,7 @@ class ProgramBase(object): ssp = parser.add_subparsers( dest="subparser_level_{0}".format(level),) for method_name in method_name_list: - #print('method', ' ' * level, method_name) + # print('method', ' ' * level, method_name) method = getattr(self, method_name) all_methods_with_sub_parsers.append(method) info = method._sub_parser @@ -231,16 +246,20 @@ class ProgramBase(object): except TypeError: print('args, kw', arg, kw) if global_option: - #print('global option', arg, len(all_methods_with_sub_parsers)) + # print('global option', + # arg, len(all_methods_with_sub_parsers)) for m in all_methods_with_sub_parsers: sp = m._sub_parser['parser'] - sp.add_argument(*arg, **kw) + # adding _globa_option to allow easy check e.g. in + # AppConfig._set_section_defaults + sp.add_argument(*arg, **kw)._global_option = True + self._program_base_initialising = False - #print('-------------------') - #dump(ProgramBase._methods_with_sub_parsers) + # print('-------------------') + # dump(ProgramBase._methods_with_sub_parsers) if False: + # for x in ProgramBase._methods_with_sub_parsers: for x in dir(cls): - #for x in ProgramBase._methods_with_sub_parsers: if x.startswith('_'): continue method = getattr(self, x) @@ -258,7 +277,7 @@ class ProgramBase(object): if level > max_depth: raise NotImplementedError for method in all_methods_with_sub_parsers: - if not method in methods_with_sub_parsers: + if method not in methods_with_sub_parsers: continue parent = method._sub_parser['kw'].get('_parent', None) sub_parsers = self._sub_parsers @@ -266,7 +285,7 @@ class ProgramBase(object): method._sub_parser['level'] = 0 # parent sub parser elif 'level' not in parent._sub_parser: - #print('skipping', parent.__name__, method.__name__) + # print('skipping', parent.__name__, method.__name__) continue else: # have a parent # make sure _parent is no longer in kw @@ -327,19 +346,23 @@ class ProgramBase(object): except TypeError: print('args, kw', arg, kw) if global_option: - #print('global option', arg, len(all_methods_with_sub_parsers)) + # print('global option', arg, + # len(all_methods_with_sub_parsers)) for m in all_methods_with_sub_parsers: sp = m._sub_parser['parser'] sp.add_argument(*arg, **kw) def _parse_args(self, *args, **kw): + name = kw.pop('default_sub_parser', None) + if name is not None: + self._parser.set_default_subparser(name, args=kw.get('args')) self._args = self._parser.parse_args(*args, **kw) return self._args - #def _parse_known_args(self, *args, **kw): - # self._args, self._unknown_args = \ - # self._parser.parse_known_args(*args, **kw) - # return self._args + # def _parse_known_args(self, *args, **kw): + # self._args, self._unknown_args = \ + # self._parser.parse_known_args(*args, **kw) + # return self._args @staticmethod def _pb_option(*args, **kw): @@ -401,19 +424,24 @@ class ProgramBase(object): def option(*args, **keywords): """\ -args: - name or flags - Either a name or a list of option strings, e.g. foo or -f, --foo. -keywords: - action - The basic type of action to be taken when this argument is encountered at the command line. - nargs - The number of command-line arguments that should be consumed. - const - A constant value required by some action and nargs selections. - default - The value produced if the argument is absent from the command line. - type - The type to which the command-line argument should be converted. - choices - A container of the allowable values for the argument. - required - Whether or not the command-line option may be omitted (optionals only). - help - A brief description of what the argument does. - metavar - A name for the argument in usage messages. - dest - The name of the attribute to be added to the object returned by parse_args(). + args: + name or flags - Either a name or a list of option strings, e.g. foo or + -f, --foo. + keywords: + action - The basic type of action to be taken when this argument is + encountered at the command line. + nargs - The number of command-line arguments that should be consumed. + const - A constant value required by some action and nargs selections. + default - The value produced if the argument is absent from the command + line. + type - The type to which the command-line argument should be converted. + choices - A container of the allowable values for the argument. + required - Whether or not the command-line option may be omitted + (optionals only). + help - A brief description of what the argument does. + metavar - A name for the argument in usage messages. + dest - The name of the attribute to be added to the object returned by + parse_args(). """ return ProgramBase._pb_option(*args, **keywords) @@ -425,3 +453,35 @@ def sub_parser(*args, **kw): def version(version_string): return ProgramBase._pb_option( '--version', action='version', version=version_string) + + +# extra ArgumentParser functionality + +def set_default_subparser(self, name, args=None): + """default subparser selection. Call after setup, just before parse_args() + name: is the name of the subparser to call by default + args: if set is the argument list handed to parse_args() + + , tested with 2.7, 3.2, 3.3, 3.4 + it works with 2.6 assuming argparse is installed + """ + subparser_found = False + for arg in sys.argv[1:]: + if arg in ['-h', '--help']: # global help if no subparser + break + else: + for x in self._subparsers._actions: + if not isinstance(x, argparse._SubParsersAction): + continue + for sp_name in x._name_parser_map.keys(): + if sp_name in sys.argv[1:]: + subparser_found = True + if not subparser_found: + # insert default in first position, this implies no + # global options without a sub_parsers specified + if args is None: + sys.argv.insert(1, name) + else: + args.insert(0, name) + +argparse.ArgumentParser.set_default_subparser = set_default_subparser @@ -1,5 +1,5 @@ [tox] -envlist = py27,py34 +envlist = py26,py27,py33,py34 [testenv] commands = py.test test |