for bool, generate --no-xxxx option
This commit is contained in:
parent
b5c50071b5
commit
f25df1f1f4
2 changed files with 120 additions and 65 deletions
|
@ -59,7 +59,7 @@ def get_config(has_tree=False):
|
||||||
|
|
||||||
|
|
||||||
def test_readme_help():
|
def test_readme_help():
|
||||||
output = """usage: prog.py [-h] [-v] {str,list,int,none}
|
output = """usage: prog.py [-h] [-v] [-nv] {str,list,int,none}
|
||||||
|
|
||||||
positional arguments:
|
positional arguments:
|
||||||
{str,list,int,none} choice the sub argument
|
{str,list,int,none} choice the sub argument
|
||||||
|
@ -67,6 +67,7 @@ positional arguments:
|
||||||
optional arguments:
|
optional arguments:
|
||||||
-h, --help show this help message and exit
|
-h, --help show this help message and exit
|
||||||
-v, --verbosity increase output verbosity
|
-v, --verbosity increase output verbosity
|
||||||
|
-nv, --no-verbosity
|
||||||
"""
|
"""
|
||||||
parser = TiramisuCmdlineParser(get_config(), 'prog.py')
|
parser = TiramisuCmdlineParser(get_config(), 'prog.py')
|
||||||
f = StringIO()
|
f = StringIO()
|
||||||
|
@ -76,7 +77,7 @@ optional arguments:
|
||||||
|
|
||||||
|
|
||||||
def test_readme_help_tree():
|
def test_readme_help_tree():
|
||||||
output = """usage: prog.py [-h] [-v] {str,list,int,none}
|
output = """usage: prog.py [-h] [-v] [-nv] {str,list,int,none}
|
||||||
|
|
||||||
optional arguments:
|
optional arguments:
|
||||||
-h, --help show this help message and exit
|
-h, --help show this help message and exit
|
||||||
|
@ -84,6 +85,7 @@ optional arguments:
|
||||||
root:
|
root:
|
||||||
{str,list,int,none} choice the sub argument
|
{str,list,int,none} choice the sub argument
|
||||||
-v, --root.verbosity increase output verbosity
|
-v, --root.verbosity increase output verbosity
|
||||||
|
-nv, --root.no-verbosity
|
||||||
"""
|
"""
|
||||||
parser = TiramisuCmdlineParser(get_config(True), 'prog.py')
|
parser = TiramisuCmdlineParser(get_config(True), 'prog.py')
|
||||||
f = StringIO()
|
f = StringIO()
|
||||||
|
@ -93,7 +95,7 @@ root:
|
||||||
|
|
||||||
|
|
||||||
def test_readme_help_tree_flatten():
|
def test_readme_help_tree_flatten():
|
||||||
output = """usage: prog.py [-h] [-v] {str,list,int,none}
|
output = """usage: prog.py [-h] [-v] [-nv] {str,list,int,none}
|
||||||
|
|
||||||
optional arguments:
|
optional arguments:
|
||||||
-h, --help show this help message and exit
|
-h, --help show this help message and exit
|
||||||
|
@ -101,6 +103,7 @@ optional arguments:
|
||||||
root:
|
root:
|
||||||
{str,list,int,none} choice the sub argument
|
{str,list,int,none} choice the sub argument
|
||||||
-v, --verbosity increase output verbosity
|
-v, --verbosity increase output verbosity
|
||||||
|
-nv, --no-verbosity
|
||||||
"""
|
"""
|
||||||
parser = TiramisuCmdlineParser(get_config(True), 'prog.py', fullpath=False)
|
parser = TiramisuCmdlineParser(get_config(True), 'prog.py', fullpath=False)
|
||||||
f = StringIO()
|
f = StringIO()
|
||||||
|
@ -110,11 +113,12 @@ root:
|
||||||
|
|
||||||
|
|
||||||
def test_readme_help_modif_positional():
|
def test_readme_help_modif_positional():
|
||||||
output = """usage: prog.py str [-h] [-v] --str STR
|
output = """usage: prog.py str [-h] [-v] [-nv] --str STR
|
||||||
|
|
||||||
optional arguments:
|
optional arguments:
|
||||||
-h, --help show this help message and exit
|
-h, --help show this help message and exit
|
||||||
-v, --verbosity increase output verbosity
|
-v, --verbosity increase output verbosity
|
||||||
|
-nv, --no-verbosity
|
||||||
--str STR string option
|
--str STR string option
|
||||||
"""
|
"""
|
||||||
parser = TiramisuCmdlineParser(get_config(), 'prog.py')
|
parser = TiramisuCmdlineParser(get_config(), 'prog.py')
|
||||||
|
@ -130,11 +134,12 @@ optional arguments:
|
||||||
|
|
||||||
|
|
||||||
def test_readme_help_modif():
|
def test_readme_help_modif():
|
||||||
output = """usage: prog.py str --str toto [-h] [-v]
|
output = """usage: prog.py str --str toto [-h] [-v] [-nv]
|
||||||
|
|
||||||
optional arguments:
|
optional arguments:
|
||||||
-h, --help show this help message and exit
|
-h, --help show this help message and exit
|
||||||
-v, --verbosity increase output verbosity
|
-v, --verbosity increase output verbosity
|
||||||
|
-nv, --no-verbosity
|
||||||
"""
|
"""
|
||||||
parser = TiramisuCmdlineParser(get_config(), 'prog.py')
|
parser = TiramisuCmdlineParser(get_config(), 'prog.py')
|
||||||
f = StringIO()
|
f = StringIO()
|
||||||
|
@ -167,8 +172,27 @@ optional arguments:
|
||||||
assert f.getvalue() == output
|
assert f.getvalue() == output
|
||||||
|
|
||||||
|
|
||||||
|
def test_readme_help_modif_short_no():
|
||||||
|
output = """usage: prog.py str --verbosity [-h] --str STR
|
||||||
|
|
||||||
|
optional arguments:
|
||||||
|
-h, --help show this help message and exit
|
||||||
|
--str STR string option
|
||||||
|
"""
|
||||||
|
parser = TiramisuCmdlineParser(get_config(), 'prog.py')
|
||||||
|
f = StringIO()
|
||||||
|
with redirect_stdout(f):
|
||||||
|
try:
|
||||||
|
parser.parse_args(['str', '-nv', '--help'])
|
||||||
|
except SystemExit as err:
|
||||||
|
assert str(err) == "0"
|
||||||
|
else:
|
||||||
|
raise Exception('must raises')
|
||||||
|
assert f.getvalue() == output
|
||||||
|
|
||||||
|
|
||||||
def test_readme_positional_mandatory():
|
def test_readme_positional_mandatory():
|
||||||
output = """usage: prog.py [-h] [-v] {str,list,int,none}
|
output = """usage: prog.py [-h] [-v] [-nv] {str,list,int,none}
|
||||||
prog.py: error: the following arguments are required: cmd
|
prog.py: error: the following arguments are required: cmd
|
||||||
"""
|
"""
|
||||||
parser = TiramisuCmdlineParser(get_config(), 'prog.py')
|
parser = TiramisuCmdlineParser(get_config(), 'prog.py')
|
||||||
|
@ -184,7 +208,7 @@ prog.py: error: the following arguments are required: cmd
|
||||||
|
|
||||||
|
|
||||||
def test_readme_positional_mandatory_tree():
|
def test_readme_positional_mandatory_tree():
|
||||||
output = """usage: prog.py [-h] [-v] {str,list,int,none}
|
output = """usage: prog.py [-h] [-v] [-nv] {str,list,int,none}
|
||||||
prog.py: error: the following arguments are required: root.cmd
|
prog.py: error: the following arguments are required: root.cmd
|
||||||
"""
|
"""
|
||||||
parser = TiramisuCmdlineParser(get_config(True), 'prog.py')
|
parser = TiramisuCmdlineParser(get_config(True), 'prog.py')
|
||||||
|
@ -200,7 +224,7 @@ prog.py: error: the following arguments are required: root.cmd
|
||||||
|
|
||||||
|
|
||||||
def test_readme_positional_mandatory_tree_flatten():
|
def test_readme_positional_mandatory_tree_flatten():
|
||||||
output = """usage: prog.py [-h] [-v] {str,list,int,none}
|
output = """usage: prog.py [-h] [-v] [-nv] {str,list,int,none}
|
||||||
prog.py: error: the following arguments are required: cmd
|
prog.py: error: the following arguments are required: cmd
|
||||||
"""
|
"""
|
||||||
parser = TiramisuCmdlineParser(get_config(True), 'prog.py', fullpath=False)
|
parser = TiramisuCmdlineParser(get_config(True), 'prog.py', fullpath=False)
|
||||||
|
@ -216,7 +240,7 @@ prog.py: error: the following arguments are required: cmd
|
||||||
|
|
||||||
|
|
||||||
def test_readme_mandatory():
|
def test_readme_mandatory():
|
||||||
output = """usage: prog.py str [-h] [-v] --str STR
|
output = """usage: prog.py str [-h] [-v] [-nv] --str STR
|
||||||
prog.py: error: the following arguments are required: --str
|
prog.py: error: the following arguments are required: --str
|
||||||
"""
|
"""
|
||||||
parser = TiramisuCmdlineParser(get_config(), 'prog.py')
|
parser = TiramisuCmdlineParser(get_config(), 'prog.py')
|
||||||
|
@ -232,7 +256,7 @@ prog.py: error: the following arguments are required: --str
|
||||||
|
|
||||||
|
|
||||||
def test_readme_mandatory_tree():
|
def test_readme_mandatory_tree():
|
||||||
output = """usage: prog.py str [-h] [-v] --root.str STR
|
output = """usage: prog.py str [-h] [-v] [-nv] --root.str STR
|
||||||
prog.py: error: the following arguments are required: --root.str
|
prog.py: error: the following arguments are required: --root.str
|
||||||
"""
|
"""
|
||||||
parser = TiramisuCmdlineParser(get_config(True), 'prog.py')
|
parser = TiramisuCmdlineParser(get_config(True), 'prog.py')
|
||||||
|
@ -248,7 +272,7 @@ prog.py: error: the following arguments are required: --root.str
|
||||||
|
|
||||||
|
|
||||||
def test_readme_mandatory_tree_flatten():
|
def test_readme_mandatory_tree_flatten():
|
||||||
output = """usage: prog.py str [-h] [-v] --str STR
|
output = """usage: prog.py str [-h] [-v] [-nv] --str STR
|
||||||
prog.py: error: the following arguments are required: --str
|
prog.py: error: the following arguments are required: --str
|
||||||
"""
|
"""
|
||||||
parser = TiramisuCmdlineParser(get_config(True), 'prog.py', fullpath=False)
|
parser = TiramisuCmdlineParser(get_config(True), 'prog.py', fullpath=False)
|
||||||
|
@ -264,7 +288,7 @@ prog.py: error: the following arguments are required: --str
|
||||||
|
|
||||||
|
|
||||||
def test_readme_cross():
|
def test_readme_cross():
|
||||||
output = """usage: prog.py none [-h] [-v]
|
output = """usage: prog.py none [-h] [-v] [-nv]
|
||||||
prog.py: error: unrecognized arguments: --int
|
prog.py: error: unrecognized arguments: --int
|
||||||
"""
|
"""
|
||||||
parser = TiramisuCmdlineParser(get_config(), 'prog.py')
|
parser = TiramisuCmdlineParser(get_config(), 'prog.py')
|
||||||
|
@ -280,7 +304,7 @@ prog.py: error: unrecognized arguments: --int
|
||||||
|
|
||||||
|
|
||||||
def test_readme_cross_tree():
|
def test_readme_cross_tree():
|
||||||
output = """usage: prog.py none [-h] [-v]
|
output = """usage: prog.py none [-h] [-v] [-nv]
|
||||||
prog.py: error: unrecognized arguments: --int
|
prog.py: error: unrecognized arguments: --int
|
||||||
"""
|
"""
|
||||||
parser = TiramisuCmdlineParser(get_config(True), 'prog.py')
|
parser = TiramisuCmdlineParser(get_config(True), 'prog.py')
|
||||||
|
@ -296,7 +320,7 @@ prog.py: error: unrecognized arguments: --int
|
||||||
|
|
||||||
|
|
||||||
def test_readme_cross_tree_flatten():
|
def test_readme_cross_tree_flatten():
|
||||||
output = """usage: prog.py none [-h] [-v]
|
output = """usage: prog.py none [-h] [-v] [-nv]
|
||||||
prog.py: error: unrecognized arguments: --int
|
prog.py: error: unrecognized arguments: --int
|
||||||
"""
|
"""
|
||||||
parser = TiramisuCmdlineParser(get_config(True), 'prog.py', fullpath=False)
|
parser = TiramisuCmdlineParser(get_config(True), 'prog.py', fullpath=False)
|
||||||
|
@ -388,6 +412,17 @@ def test_readme_int_verbosity_short():
|
||||||
assert config.value.dict() == output
|
assert config.value.dict() == output
|
||||||
|
|
||||||
|
|
||||||
|
def test_readme_int_verbosity_short_no():
|
||||||
|
output = {'cmd': 'int',
|
||||||
|
'int': 3,
|
||||||
|
'verbosity': False,
|
||||||
|
'v': False}
|
||||||
|
config = get_config()
|
||||||
|
parser = TiramisuCmdlineParser(config, 'prog.py')
|
||||||
|
parser.parse_args(['int', '--int', '3', '-nv'])
|
||||||
|
assert config.value.dict() == output
|
||||||
|
|
||||||
|
|
||||||
def test_readme_int_verbosity_short_tree():
|
def test_readme_int_verbosity_short_tree():
|
||||||
output = {'root.cmd': 'int',
|
output = {'root.cmd': 'int',
|
||||||
'root.int': 3,
|
'root.int': 3,
|
||||||
|
|
|
@ -12,10 +12,11 @@
|
||||||
#
|
#
|
||||||
# You should have received a copy of the GNU Lesser General Public License
|
# You should have received a copy of the GNU Lesser General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
from typing import Union, List, Optional
|
from typing import Union, List, Optional
|
||||||
from argparse import ArgumentParser, Namespace, SUPPRESS, _HelpAction, HelpFormatter
|
from argparse import ArgumentParser, Namespace, SUPPRESS, _HelpAction, HelpFormatter
|
||||||
|
from copy import copy
|
||||||
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from tiramisu import Config
|
from tiramisu import Config
|
||||||
from tiramisu.error import PropertiesOptionError
|
from tiramisu.error import PropertiesOptionError
|
||||||
|
@ -146,8 +147,19 @@ class TiramisuCmdlineParser(ArgumentParser):
|
||||||
def add_subparsers(self, *args, **kwargs):
|
def add_subparsers(self, *args, **kwargs):
|
||||||
raise NotImplementedError('do not use add_subparsers')
|
raise NotImplementedError('do not use add_subparsers')
|
||||||
|
|
||||||
def _gen_argument(self, name, properties):
|
def _gen_argument(self, name, longargument, no_prefix=False):
|
||||||
if len(name) == 1 and 'longargument' not in properties:
|
shortarg = len(name) == 1 and not longargument
|
||||||
|
if no_prefix:
|
||||||
|
if shortarg:
|
||||||
|
prefix = 'n'
|
||||||
|
else:
|
||||||
|
prefix = 'no-'
|
||||||
|
if '.' in name:
|
||||||
|
sname = name.rsplit('.', 1)
|
||||||
|
name = sname[0] + '.' + prefix + sname[1]
|
||||||
|
else:
|
||||||
|
name = prefix + name
|
||||||
|
if shortarg:
|
||||||
return self.prefix_chars + name
|
return self.prefix_chars + name
|
||||||
return self.prefix_chars * 2 + name
|
return self.prefix_chars * 2 + name
|
||||||
|
|
||||||
|
@ -182,42 +194,49 @@ class TiramisuCmdlineParser(ArgumentParser):
|
||||||
if option.issymlinkoption():
|
if option.issymlinkoption():
|
||||||
symlink_name = option.name(follow_symlink=True)
|
symlink_name = option.name(follow_symlink=True)
|
||||||
if symlink_name in actions:
|
if symlink_name in actions:
|
||||||
actions[symlink_name][0].insert(0, self._gen_argument(option.name(), properties))
|
actions[symlink_name][0][0].insert(0, self._gen_argument(option.name(), 'longargument' in properties))
|
||||||
|
if len(actions[symlink_name]) == 2:
|
||||||
|
actions[symlink_name][1][0].insert(0, self._gen_argument(option.name(), False, True))
|
||||||
continue
|
continue
|
||||||
if _forhelp and not obj.owner.isdefault() and obj.value.get():
|
if _forhelp and not obj.owner.isdefault() and obj.value.get() is not None:
|
||||||
if 'positional' not in properties:
|
if 'positional' not in properties:
|
||||||
self.prog += ' {}'.format(self._gen_argument(name, properties))
|
self.prog += ' {}'.format(self._gen_argument(name, 'longargument' in properties))
|
||||||
if option.type() != 'boolean':
|
if option.type() != 'boolean':
|
||||||
self.prog += ' {}'.format(obj.value.get())
|
self.prog += ' {}'.format(obj.value.get())
|
||||||
else:
|
else:
|
||||||
if 'positional' in properties:
|
if 'positional' in properties:
|
||||||
|
if option.type() == 'boolean':
|
||||||
|
raise ValueError('boolean option must not be positional')
|
||||||
if not 'mandatory' in properties:
|
if not 'mandatory' in properties:
|
||||||
raise ValueError('"positional" argument must be "mandatory" too')
|
raise ValueError('"positional" argument must be "mandatory" too')
|
||||||
if _forhelp:
|
|
||||||
args = [option.path()]
|
args = [option.path()]
|
||||||
|
if _forhelp:
|
||||||
kwargs['default'] = obj.value.default()
|
kwargs['default'] = obj.value.default()
|
||||||
else:
|
else:
|
||||||
args = [option.path()]
|
|
||||||
kwargs['default'] = obj.value.get()
|
kwargs['default'] = obj.value.get()
|
||||||
kwargs['nargs'] = '?'
|
kwargs['nargs'] = '?'
|
||||||
else:
|
else:
|
||||||
kwargs['dest'] = option.path()
|
kwargs['dest'] = option.path()
|
||||||
kwargs['default'] = SUPPRESS
|
kwargs['default'] = SUPPRESS
|
||||||
args = [self._gen_argument(name, properties)]
|
|
||||||
if _forhelp and 'mandatory' in properties:
|
if _forhelp and 'mandatory' in properties:
|
||||||
kwargs['required'] = True
|
kwargs['required'] = True
|
||||||
|
|
||||||
if option.type() == 'boolean':
|
if option.type() == 'boolean':
|
||||||
if 'mandatory' in properties:
|
|
||||||
raise ValueError('"mandatory" property is not allowed for BoolOption')
|
|
||||||
#if not isinstance(option.default(), bool):
|
|
||||||
# raise ValueError('default value is mandatory for BoolOption')
|
|
||||||
if obj.value.get() is False:
|
if obj.value.get() is False:
|
||||||
action = 'store_true'
|
action = 'store_true'
|
||||||
|
no_action = 'store_false'
|
||||||
else:
|
else:
|
||||||
action = 'store_false'
|
action = 'store_false'
|
||||||
|
no_action = 'store_true'
|
||||||
kwargs['action'] = action
|
kwargs['action'] = action
|
||||||
else:
|
args = [self._gen_argument(name, 'longargument' in properties)]
|
||||||
|
#
|
||||||
|
nkwargs = copy(kwargs)
|
||||||
|
nkwargs['action'] = no_action
|
||||||
|
del nkwargs['help']
|
||||||
|
nargs = [self._gen_argument(name, 'longargument' in properties, True)]
|
||||||
|
actions[option.name()] = [(args, kwargs), (nargs, nkwargs)]
|
||||||
|
continue
|
||||||
|
args = [self._gen_argument(name, 'longargument' in properties)]
|
||||||
if _forhelp:
|
if _forhelp:
|
||||||
value = obj.value.default()
|
value = obj.value.default()
|
||||||
else:
|
else:
|
||||||
|
@ -240,8 +259,9 @@ class TiramisuCmdlineParser(ArgumentParser):
|
||||||
else:
|
else:
|
||||||
pass
|
pass
|
||||||
#raise NotImplementedError('not supported yet')
|
#raise NotImplementedError('not supported yet')
|
||||||
actions[option.name()] = (args, kwargs)
|
actions[option.name()] = [(args, kwargs)]
|
||||||
for args, kwargs in actions.values():
|
for values in actions.values():
|
||||||
|
for args, kwargs in values:
|
||||||
group.add_argument(*args, **kwargs)
|
group.add_argument(*args, **kwargs)
|
||||||
|
|
||||||
def parse_args(self,
|
def parse_args(self,
|
||||||
|
@ -272,7 +292,7 @@ class TiramisuCmdlineParser(ArgumentParser):
|
||||||
name = key
|
name = key
|
||||||
else:
|
else:
|
||||||
name = key.rsplit('.', 1)[1]
|
name = key.rsplit('.', 1)[1]
|
||||||
args = self._gen_argument(name, self.config.option(key).property.get())
|
args = self._gen_argument(name, 'longargument' in self.config.option(key).property.get())
|
||||||
else:
|
else:
|
||||||
args = key
|
args = key
|
||||||
if not self.fullpath and '.' in args:
|
if not self.fullpath and '.' in args:
|
||||||
|
|
Loading…
Reference in a new issue