support integer choiceoption
This commit is contained in:
parent
0583c19f75
commit
dc94b37896
2 changed files with 52 additions and 15 deletions
|
@ -237,7 +237,7 @@ def test_leadership_modif_follower_choice_unknown(json):
|
||||||
[--leader.follower_boolean INDEX]
|
[--leader.follower_boolean INDEX]
|
||||||
[--leader.no-follower_boolean INDEX]
|
[--leader.no-follower_boolean INDEX]
|
||||||
[--leader.follower_choice INDEX [{opt1,opt2}]]
|
[--leader.follower_choice INDEX [{opt1,opt2}]]
|
||||||
prog.py: error: invalid choice: 'opt_unknown' (choose from 'opt1', 'opt2')
|
prog.py: error: argument --leader.follower_choice: invalid choice: 'opt_unknown' (choose from 'opt1', 'opt2')
|
||||||
"""
|
"""
|
||||||
config = get_config(json)
|
config = get_config(json)
|
||||||
parser = TiramisuCmdlineParser(config, 'prog.py')
|
parser = TiramisuCmdlineParser(config, 'prog.py')
|
||||||
|
|
|
@ -33,6 +33,17 @@ except ModuleNotFoundError:
|
||||||
ConfigJson = Config
|
ConfigJson = Config
|
||||||
|
|
||||||
|
|
||||||
|
def get_choice_list(obj, properties, display):
|
||||||
|
choices = obj.value.list()
|
||||||
|
if choices[0] == '':
|
||||||
|
del choices[0]
|
||||||
|
if display:
|
||||||
|
choices = '{{{}}}'.format(','.join(choices))
|
||||||
|
if 'mandatory' not in properties:
|
||||||
|
choices = f'[{choices}]'
|
||||||
|
return choices
|
||||||
|
|
||||||
|
|
||||||
class TiramisuNamespace(Namespace):
|
class TiramisuNamespace(Namespace):
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
config: Config,
|
config: Config,
|
||||||
|
@ -41,6 +52,7 @@ class TiramisuNamespace(Namespace):
|
||||||
super().__setattr__('_root', root)
|
super().__setattr__('_root', root)
|
||||||
super().__setattr__('list_force_no', {})
|
super().__setattr__('list_force_no', {})
|
||||||
super().__setattr__('list_force_del', {})
|
super().__setattr__('list_force_del', {})
|
||||||
|
super().__setattr__('arguments', {})
|
||||||
self._populate()
|
self._populate()
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
|
||||||
|
@ -74,6 +86,22 @@ class TiramisuNamespace(Namespace):
|
||||||
else:
|
else:
|
||||||
_setattr = self._setattr
|
_setattr = self._setattr
|
||||||
true_value = value
|
true_value = value
|
||||||
|
if option.option.type() == 'choice':
|
||||||
|
# HACK if integer in choice
|
||||||
|
values = option.value.list()
|
||||||
|
if isinstance(value, list):
|
||||||
|
int_value = []
|
||||||
|
for val in value:
|
||||||
|
if isinstance(val, str) and val.isdigit():
|
||||||
|
int_val = int(val)
|
||||||
|
if int_val in values:
|
||||||
|
val = int_val
|
||||||
|
int_value.append(val)
|
||||||
|
value = int_value
|
||||||
|
elif value not in values and isinstance(value, str) and value.isdigit():
|
||||||
|
int_value = int(value)
|
||||||
|
if int_value in values:
|
||||||
|
value = int_value
|
||||||
try:
|
try:
|
||||||
if key in self.list_force_del:
|
if key in self.list_force_del:
|
||||||
option.value.pop(value)
|
option.value.pop(value)
|
||||||
|
@ -81,7 +109,16 @@ class TiramisuNamespace(Namespace):
|
||||||
_setattr(option, true_key, key, value)
|
_setattr(option, true_key, key, value)
|
||||||
except ValueError as err:
|
except ValueError as err:
|
||||||
if option.option.type() == 'choice':
|
if option.option.type() == 'choice':
|
||||||
raise ValueError("invalid choice: '{}' (choose from {})".format(true_value, ', '.join([f"'{val}'" for val in option.value.list()])))
|
choices = get_choice_list(option, option.property.get(), False)
|
||||||
|
values = option.value.list()
|
||||||
|
if isinstance(true_value, list):
|
||||||
|
for val in value:
|
||||||
|
if val not in values:
|
||||||
|
display_value = val
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
display_value = true_value
|
||||||
|
raise ValueError("argument {}: invalid choice: '{}' (choose from {})".format(self.arguments[key], display_value, ', '.join([f"'{val}'" for val in choices])))
|
||||||
else:
|
else:
|
||||||
raise err
|
raise err
|
||||||
|
|
||||||
|
@ -173,8 +210,11 @@ class _BuildKwargs:
|
||||||
else:
|
else:
|
||||||
ga_name = name
|
ga_name = name
|
||||||
self.kwargs['dest'] = self.gen_argument_name(option.path(), False)
|
self.kwargs['dest'] = self.gen_argument_name(option.path(), False)
|
||||||
self.args = [self.cmdlineparser._gen_argument(ga_name, is_short_name)]
|
argument = self.cmdlineparser._gen_argument(ga_name, is_short_name)
|
||||||
|
self.cmdlineparser.namespace.arguments[option.path()] = argument
|
||||||
|
self.args = [argument]
|
||||||
else:
|
else:
|
||||||
|
self.cmdlineparser.namespace.arguments[option.path()] = option.path()
|
||||||
self.args = [option.path()]
|
self.args = [option.path()]
|
||||||
|
|
||||||
def __setitem__(self,
|
def __setitem__(self,
|
||||||
|
@ -191,7 +231,9 @@ class _BuildKwargs:
|
||||||
name = self.gen_argument_name(option.name(), is_short_name)
|
name = self.gen_argument_name(option.name(), is_short_name)
|
||||||
else:
|
else:
|
||||||
name = option.name()
|
name = option.name()
|
||||||
self.args.insert(0, self.cmdlineparser._gen_argument(name, is_short_name))
|
argument = self.cmdlineparser._gen_argument(name, is_short_name)
|
||||||
|
self.cmdlineparser.namespace.arguments[option.path()] = argument
|
||||||
|
self.args.insert(0, argument)
|
||||||
|
|
||||||
def gen_argument_name(self, name, is_short_name):
|
def gen_argument_name(self, name, is_short_name):
|
||||||
if self.force_no:
|
if self.force_no:
|
||||||
|
@ -467,14 +509,9 @@ class TiramisuCmdlineParser(ArgumentParser):
|
||||||
kwargs['nargs'] = 2
|
kwargs['nargs'] = 2
|
||||||
if _forhelp and 'mandatory' not in properties:
|
if _forhelp and 'mandatory' not in properties:
|
||||||
metavar = f'[{metavar}]'
|
metavar = f'[{metavar}]'
|
||||||
if option.type() == 'choice':
|
if option.type() == 'choice' and _forhelp:
|
||||||
choice_list = obj.value.list()
|
# do not manage choice with argparse there is problem with integer problem
|
||||||
if choice_list[0] == '':
|
kwargs['metavar'] = ('INDEX', get_choice_list(obj, properties, True))
|
||||||
del choice_list[0]
|
|
||||||
choices = '{{{}}}'.format(','.join(choice_list))
|
|
||||||
if 'mandatory' not in properties:
|
|
||||||
choices = f'[{choices}]'
|
|
||||||
kwargs['metavar'] = ('INDEX', choices)
|
|
||||||
else:
|
else:
|
||||||
kwargs['metavar'] = ('INDEX', metavar)
|
kwargs['metavar'] = ('INDEX', metavar)
|
||||||
if force_del:
|
if force_del:
|
||||||
|
@ -488,11 +525,11 @@ class TiramisuCmdlineParser(ArgumentParser):
|
||||||
if _forhelp and option.type() == 'boolean':
|
if _forhelp and option.type() == 'boolean':
|
||||||
kwargs['metavar'] = 'INDEX'
|
kwargs['metavar'] = 'INDEX'
|
||||||
kwargs['nargs'] = 1
|
kwargs['nargs'] = 1
|
||||||
elif option.type() == 'choice' and not option.isfollower():
|
elif option.type() == 'choice' and not option.isfollower() and _forhelp:
|
||||||
kwargs['choices'] = obj.value.list()
|
# do not manage choice with argparse there is problem with integer problem
|
||||||
|
kwargs['choices'] = get_choice_list(obj, properties, False)
|
||||||
else:
|
else:
|
||||||
pass
|
pass
|
||||||
#raise NotImplementedError('not supported yet')
|
|
||||||
actions.setdefault(option.name(), []).append(kwargs)
|
actions.setdefault(option.name(), []).append(kwargs)
|
||||||
for option_is_not_default in options_is_not_default.values():
|
for option_is_not_default in options_is_not_default.values():
|
||||||
self._option_is_not_default(**option_is_not_default)
|
self._option_is_not_default(**option_is_not_default)
|
||||||
|
|
Loading…
Reference in a new issue