support suboptiondescription in TiramisuCmdLineParser

This commit is contained in:
2019-07-26 10:56:31 +02:00
parent 9db0942291
commit e14b997a54
9 changed files with 12758 additions and 21 deletions

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018 Team tiramisu (see AUTHORS for all contributors)
# Copyright (C) 2018-2019 Team tiramisu (see AUTHORS for all contributors)
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by the
@ -35,19 +35,25 @@ except ModuleNotFoundError:
class TiramisuNamespace(Namespace):
def __init__(self,
config: Config) -> None:
config: Config,
root: Optional[str]) -> None:
super().__setattr__('_config', config)
super().__setattr__('_root', root)
super().__setattr__('list_force_no', {})
self._populate()
super().__init__()
def _populate(self) -> None:
for tiramisu_key, tiramisu_value in self._config.value.dict().items():
if self._root is None:
config = self._config
else:
config = self._config.option(self._root)
for tiramisu_key, tiramisu_value in config.value.dict(fullpath=True).items():
option = self._config.option(tiramisu_key)
if not option.option.issymlinkoption():
if tiramisu_value == [] and \
option.option.ismulti() and \
option.owner.isdefault():
option.option.ismulti(): # and \
# option.owner.isdefault():
tiramisu_value = None
super().__setattr__(tiramisu_key, tiramisu_value)
@ -106,7 +112,7 @@ class TiramisuHelpFormatter(HelpFormatter):
action):
ret = super()._get_default_metavar_for_optional(action)
if '.' in ret:
ret = ret.split('.', 1)[1]
ret = ret.rsplit('.', 1)[1]
return ret
@ -179,17 +185,24 @@ class TiramisuCmdlineParser(ArgumentParser):
def __init__(self,
config: Union[Config, ConfigJson],
*args,
root: str=None,
fullpath: bool=True,
_forhelp: bool=False,
**kwargs):
self.fullpath = fullpath
self.config = config
self.root = root
kwargs['formatter_class'] = TiramisuHelpFormatter
self.namespace = TiramisuNamespace(self.config)
if self.root is None:
subconfig = self.config.option
else:
subconfig = self.config.option(self.root)
self.namespace = TiramisuNamespace(self.config, self.root)
super().__init__(*args, **kwargs)
self.register('action', 'help', _TiramisuHelpAction)
self._config_to_argparser(_forhelp,
self.config.option)
subconfig,
self.root)
def _pop_action_class(self, kwargs, default=None):
ret = super()._pop_action_class(kwargs, default)
@ -231,6 +244,7 @@ class TiramisuCmdlineParser(ArgumentParser):
# so create a new parser
new_parser = TiramisuCmdlineParser(self.config,
self.prog,
root=self.root,
fullpath=self.fullpath)
namespace_, args_ = new_parser._parse_known_args(args_, namespace)
else:
@ -275,12 +289,14 @@ class TiramisuCmdlineParser(ArgumentParser):
continue
if obj.option.isoptiondescription():
if _forhelp:
group = self.add_argument_group(obj.option.doc())
newgroup = self.add_argument_group(obj.option.path(), obj.option.doc())
else:
newgroup = group
if prefix:
prefix_ = prefix + '.' + obj.option.name()
else:
prefix_ = obj.option.path()
self._config_to_argparser(_forhelp, obj, prefix_, group)
self._config_to_argparser(_forhelp, obj, prefix_, newgroup)
elif obj.option.type() == 'boolean' and not obj.option.issymlinkoption():
yield obj, False
yield obj, True
@ -290,7 +306,7 @@ class TiramisuCmdlineParser(ArgumentParser):
def _config_to_argparser(self,
_forhelp: bool,
config,
prefix: Optional[str]=None,
prefix: Optional[str],
group=None) -> None:
if group is None:
group = super()
@ -298,6 +314,15 @@ class TiramisuCmdlineParser(ArgumentParser):
leadership_len = None
for obj, force_no in self._config_list(config, prefix, _forhelp, group):
option = obj.option
name = option.name()
if name.startswith(self.prefix_chars):
raise ValueError(_('name cannot startswith "{}"').format(self.prefix_chars))
if option.issymlinkoption():
symlink_name = option.name(follow_symlink=True)
if symlink_name in actions:
for action in actions[symlink_name]:
action.add_argument(option)
continue
if option.isleader():
value = obj.value.get()
leadership_len = len(value)
@ -307,21 +332,12 @@ class TiramisuCmdlineParser(ArgumentParser):
value.append(self.config.option(obj.option.path(), index).value.get())
else:
value = obj.value.get()
name = option.name()
if name.startswith(self.prefix_chars):
raise ValueError(_('name cannot startswith "{}"').format(self.prefix_chars))
if self.fullpath and prefix:
name = prefix + '.' + name
if option.isfollower():
properties = obj.option.properties()
else:
properties = obj.property.get()
if option.issymlinkoption():
symlink_name = option.name(follow_symlink=True)
if symlink_name in actions:
for action in actions[symlink_name]:
action.add_argument(option)
continue
kwargs = _BuildKwargs(name, option, self, properties, force_no)
if not option.isfollower() and _forhelp and not obj.owner.isdefault() and value is not None:
if not force_no:
@ -462,6 +478,7 @@ class TiramisuCmdlineParser(ArgumentParser):
**kwargs):
help_formatter = TiramisuCmdlineParser(self.config,
self.prog,
root=self.root,
fullpath=self.fullpath,
_forhelp=True)
return super(TiramisuCmdlineParser, help_formatter).format_usage(*args, **kwargs)
@ -469,6 +486,7 @@ class TiramisuCmdlineParser(ArgumentParser):
def format_help(self):
help_formatter = TiramisuCmdlineParser(self.config,
self.prog,
root=self.root,
fullpath=self.fullpath,
_forhelp=True)
return super(TiramisuCmdlineParser, help_formatter).format_help()