Compare commits
No commits in common. "7090b6bcbce5365a19aeccc7e64a1306b9df0b9a" and "6d01f9ffee7f01522cf256b6179bc4b7e137208d" have entirely different histories.
7090b6bcbc
...
6d01f9ffee
49 changed files with 505 additions and 15198 deletions
File diff suppressed because one or more lines are too long
|
|
@ -1,303 +0,0 @@
|
|||
import re, random, ipaddress
|
||||
def get_version(*args, **kwargs):
|
||||
return u'2.6.2'
|
||||
|
||||
|
||||
def is_instanciate(*args, **kwargs):
|
||||
return 'oui'
|
||||
|
||||
|
||||
def calc_val(valeur):
|
||||
return valeur
|
||||
|
||||
|
||||
def concat(*args, **kwargs):
|
||||
""" concatène deux valeurs """
|
||||
sortedkeys = list(kwargs.keys())
|
||||
sortedkeys.sort()
|
||||
sortedkwvalues = []
|
||||
for key in sortedkeys:
|
||||
if kwargs[key] == '' or kwargs[key] is None:
|
||||
return None
|
||||
sortedkwvalues.append(kwargs[key])
|
||||
if None in args:
|
||||
return None
|
||||
return "".join(args)+''.join(sortedkwvalues)
|
||||
|
||||
|
||||
def auto_dns(*args, **kwargs):
|
||||
return []
|
||||
|
||||
|
||||
def calc_multi_condition(param, match=None, mismatch=None, operator='AND',
|
||||
default_match=None, default_mismatch=None,
|
||||
eval_match='False', eval_mismatch='False',
|
||||
**conditions):
|
||||
if operator not in ('AND', 'OR'):
|
||||
raise ValueError(_(u'Operator must be either "AND" or "OR"'))
|
||||
if eval_match not in ('True', 'False'):
|
||||
raise ValueError(_(u'eval_match must be either "True" or "False"'))
|
||||
if eval_mismatch not in ('True', 'False'):
|
||||
raise ValueError(_(u'eval_mismatch must be either "True" or "False"'))
|
||||
if match is None:
|
||||
if default_match is None:
|
||||
match = u'oui'
|
||||
else:
|
||||
if default_match == 'None':
|
||||
match = None
|
||||
else:
|
||||
match = default_match
|
||||
if mismatch is None:
|
||||
if default_mismatch is None:
|
||||
mismatch = u'non'
|
||||
else:
|
||||
if default_mismatch == 'None':
|
||||
mismatch = None
|
||||
else:
|
||||
mismatch = default_mismatch
|
||||
conditions_keys = list(conditions.keys())
|
||||
conditions_keys.sort()
|
||||
for condition in conditions_keys:
|
||||
if not condition.startswith('condition_'):
|
||||
raise ValueError(_(u'Condition keys must start with "condition".'))
|
||||
# si le paramètre est une liste...
|
||||
if param.startswith('['):
|
||||
param = eval(param)
|
||||
# si il faut évaluer le résultat à retourner...
|
||||
if eval_match == 'True':
|
||||
match = eval(match)
|
||||
if eval_mismatch == 'True':
|
||||
mismatch = eval(mismatch)
|
||||
if isinstance(param, list) and len(param) != len(conditions):
|
||||
raise ValueError(_(u'Conditions and parameters counts do not match in calc_multi_condition.'))
|
||||
for num in range(0, len(conditions)):
|
||||
key = conditions_keys[num]
|
||||
value = conditions[key]
|
||||
if not isinstance(param, list):
|
||||
if operator == 'AND' and value != param:
|
||||
return mismatch
|
||||
if operator == 'OR' and value == param:
|
||||
return match
|
||||
else:
|
||||
if operator == 'AND' and value != param[num]:
|
||||
return mismatch
|
||||
if operator == 'OR' and value == param[num]:
|
||||
return match
|
||||
if operator == 'AND':
|
||||
return match
|
||||
else:
|
||||
return mismatch
|
||||
|
||||
|
||||
auto_copy_val = calc_val
|
||||
|
||||
|
||||
def activate_master_only_web_app(*args, **kwargs):
|
||||
return 'oui'
|
||||
|
||||
|
||||
def calc_val_first_value(*args, **kwargs):
|
||||
if args == tuple():
|
||||
return None
|
||||
return args[0]
|
||||
|
||||
|
||||
def valid_entier(*args, **kwargs):
|
||||
return True
|
||||
|
||||
|
||||
def list_cdrom_devices(*args, **kwargs):
|
||||
return 'cdrom'
|
||||
|
||||
|
||||
def cdrom_minormajor(*args, **kwargs):
|
||||
return 0
|
||||
|
||||
|
||||
def calc_free_PE(*args, **kwargs):
|
||||
return 0
|
||||
|
||||
|
||||
def enable_lv_creation(*args, **kwargs):
|
||||
return "oui"
|
||||
|
||||
|
||||
def get_lv_names(*args, **kwargs):
|
||||
return "lvm"
|
||||
|
||||
|
||||
def calc_multi_val(*args, **kwargs):
|
||||
res = []
|
||||
for arg in args:
|
||||
if arg is None:
|
||||
if kwargs.get('allow_none', u'False') == u'True':
|
||||
continue
|
||||
else:
|
||||
return []
|
||||
# gestion des valeurs multi
|
||||
if isinstance(arg, list):
|
||||
for ev_arg in arg:
|
||||
if ev_arg is not None and ev_arg not in res:
|
||||
res.append(ev_arg)
|
||||
else:
|
||||
res.append(arg)
|
||||
return res
|
||||
|
||||
|
||||
def check_partitioning_auto_extend(*args, **kwargs):
|
||||
return 'non'
|
||||
|
||||
|
||||
def check_free_space(*args, **kwargs):
|
||||
return 0
|
||||
|
||||
|
||||
def is_fs_type(*args, **kwargs):
|
||||
return "ext4"
|
||||
|
||||
|
||||
def is_lv_name(*args, **kwargs):
|
||||
return "/etc"
|
||||
|
||||
|
||||
def get_net_device(*args, **kwargs):
|
||||
return 'eth' + str(args[0])
|
||||
|
||||
|
||||
def list_len_gt(param, max_len=None, match=None, mismatch=None,
|
||||
default_match=None, default_mismatch=None,
|
||||
eval_match='False', eval_mismatch='False',):
|
||||
if match is None:
|
||||
if default_match is None:
|
||||
match = u'oui'
|
||||
else:
|
||||
if default_match == 'None':
|
||||
match = None
|
||||
else:
|
||||
match = default_match
|
||||
if mismatch is None:
|
||||
if default_mismatch is None:
|
||||
mismatch = u'non'
|
||||
else:
|
||||
if default_mismatch == 'None':
|
||||
mismatch = None
|
||||
else:
|
||||
mismatch = default_mismatch
|
||||
# si il faut évaluer le résultat à retourner...
|
||||
if eval_match == 'True':
|
||||
match = eval(match)
|
||||
if eval_mismatch == 'True':
|
||||
mismatch = eval(mismatch)
|
||||
if isinstance(param, list):
|
||||
if len(param) > int(max_len):
|
||||
return match
|
||||
else:
|
||||
return mismatch
|
||||
else:
|
||||
return mismatch
|
||||
|
||||
|
||||
def get_zone_name_bridge(*args, **kwargs):
|
||||
return "non"
|
||||
|
||||
|
||||
def get_zone_name(*args, **kwargs):
|
||||
return 'eth0'
|
||||
|
||||
def auto_eth(*args, **kwargs):
|
||||
if kwargs['parametre'] == kwargs['condition']:
|
||||
return "192.168.1.1"
|
||||
|
||||
|
||||
def auto_netmask(*args, **kwargs):
|
||||
if kwargs['parametre'] == kwargs['condition']:
|
||||
return "255.255.255.0"
|
||||
|
||||
|
||||
def calc_or_auto_network(*args, **kwargs):
|
||||
if kwargs['parametre'] == kwargs['condition']:
|
||||
return "192.168.1.0"
|
||||
return calc_network(kwargs['ip'], kwargs['netmask'])
|
||||
|
||||
|
||||
def calc_or_auto_broadcast(*args, **kwargs):
|
||||
if kwargs['parametre'] == kwargs['condition']:
|
||||
return "192.168.1.255"
|
||||
|
||||
|
||||
def auto_defaultgw_ip(*args, **kwargs):
|
||||
if args[0] != 'statique':
|
||||
return "192.168.1.254"
|
||||
|
||||
|
||||
def calc_network(ip, netmask):
|
||||
if None not in (ip, netmask):
|
||||
try:
|
||||
return str(ipaddress.ip_interface('{}/{}'.format(ip, netmask)).network.network_address)
|
||||
except:
|
||||
return None
|
||||
|
||||
|
||||
def calc_broadcast(ip, netmask):
|
||||
if None not in (ip, netmask):
|
||||
return str(ipaddress.ip_interface('{}/{}'.format(ip, netmask)).network.broadcast_address)
|
||||
|
||||
|
||||
def calc_ssl_country_name(*args, **kwargs):
|
||||
return 'FR'
|
||||
|
||||
|
||||
def valid_country(*args, **kwargs):
|
||||
return
|
||||
|
||||
|
||||
def valid_regexp(data, exp_reg, err_msg=u"Invalid syntax"):
|
||||
if data == "":
|
||||
return True
|
||||
match = re.match(exp_reg, data)
|
||||
if match is None:
|
||||
raise ValueError(err_msg)
|
||||
else:
|
||||
return True
|
||||
|
||||
|
||||
def gen_random(*args, **kwargs):
|
||||
return '4444444444444444444'
|
||||
|
||||
|
||||
def check_name_uniq(value, values, index):
|
||||
values.pop(index)
|
||||
if value in values:
|
||||
raise ValueError('le nom {} est déjà attribué à une autre plage'.format(value))
|
||||
|
||||
|
||||
def calc_classe(*args, **kwargs):
|
||||
return "24"
|
||||
|
||||
|
||||
def calc_webredirection(*args, **kwargs):
|
||||
return "/toto"
|
||||
|
||||
|
||||
def calc_container(mode_container, container_info, mode_zephir='non'):
|
||||
return container_info
|
||||
|
||||
|
||||
def calc_libelle_annuaire(*args, **kwargs):
|
||||
return "LDAP label"
|
||||
|
||||
|
||||
def valid_differ(data, value):
|
||||
if data == value:
|
||||
raise ValueError(u"Value must be different from {0}".format(value))
|
||||
|
||||
|
||||
def device_type(*args, **kwargs):
|
||||
return 'b'
|
||||
|
||||
|
||||
def random_int(vmin, vmax, exclude=None):
|
||||
values = list(range(int(vmin), int(vmax)+1))
|
||||
if exclude != None and exclude in values:
|
||||
values.remove(exclude)
|
||||
return random.choice(values)
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
"""AmonEcole example
|
||||
"""
|
||||
|
||||
from examples.AmonEcole import amonecole
|
||||
from tiramisu_cmdline_parser import TiramisuCmdlineParser
|
||||
from tiramisu import default_storage
|
||||
|
||||
|
||||
def display_name(option, dyn_name):
|
||||
return "--" + option.impl_getpath()
|
||||
|
||||
|
||||
def main():
|
||||
"""AmonEcole
|
||||
"""
|
||||
default_storage.setting(engine='sqlite3', name='amonecole_cmdline_parser')
|
||||
config = amonecole.get_config(display_name=display_name)
|
||||
config.property.read_write()
|
||||
config.property.pop('expert')
|
||||
config.property.pop('normal')
|
||||
config.property.add('expert')
|
||||
config.property.add('normal')
|
||||
config.permissive.add('expert')
|
||||
config.permissive.add('normal')
|
||||
parser = TiramisuCmdlineParser(config, root='creole')
|
||||
#parser.parse_args(valid_mandatory=False)
|
||||
parser.parse_args()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
@ -8,7 +8,9 @@ import unicodedata
|
|||
import re
|
||||
from os import unlink
|
||||
from os.path import isfile
|
||||
from tiramisu import RegexpOption, OptionDescription, Config, IntOption, UnicodeOption, BoolOption, ParamOption, Params, default_storage
|
||||
from tiramisu import RegexpOption, OptionDescription, Config, IntOption, UnicodeOption, BoolOption, ParamOption, Params
|
||||
from tiramisu.storage import storage_type
|
||||
from tiramisu.storage.sqlite3.storage import SETTING
|
||||
from tiramisu_cmdline_parser import TiramisuCmdlineParser
|
||||
|
||||
|
||||
|
|
@ -118,7 +120,7 @@ def main():
|
|||
proposal = ProposalOption('guess{}'.format(idx),
|
||||
'Guess {}'.format(idx),
|
||||
requires=requires,
|
||||
properties=('positional', 'mandatory'))
|
||||
properties=('positional',))
|
||||
#FIXME maximum recursion ...
|
||||
#if proposals:
|
||||
# proposal.impl_add_consistency('not_equal', proposals[0])
|
||||
|
|
@ -145,16 +147,15 @@ def main():
|
|||
#descr = OptionDescription('proposals',
|
||||
# 'Suggesting letters',
|
||||
# options)
|
||||
default_storage.setting(engine='sqlite3', name='hangman_cmdline_parser')
|
||||
storage_type.set('sqlite3')
|
||||
config = Config(OptionDescription('root', 'root', [word, proposal_word, misses, proposals_left] + options), persistent=True, session_id='hangman')
|
||||
config.property.read_write()
|
||||
parser = TiramisuCmdlineParser(config)
|
||||
try:
|
||||
parser = TiramisuCmdlineParser(config)
|
||||
parser.parse_args(valid_mandatory=False)
|
||||
parser.parse_args()
|
||||
except ValueError:
|
||||
# if no more suggestion
|
||||
pass
|
||||
filename = '/tmp/tiramisu.db'
|
||||
config = parser.get_config()
|
||||
filename = '{}/tiramisu.db'.format(SETTING.dir_database)
|
||||
lost = False
|
||||
for name in ['proposal_word', 'misses', 'proposals_left']:
|
||||
option = config.option(name)
|
||||
|
|
|
|||
45
setup.py
45
setup.py
|
|
@ -1,34 +1,29 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from setuptools import setup, find_packages
|
||||
import os
|
||||
from tiramisu_cmdline_parser import __version__
|
||||
|
||||
|
||||
PACKAGE_NAME = os.environ.get('PACKAGE_DST', 'tiramisu_cmdline_parser')
|
||||
import tiramisu_cmdline_parser
|
||||
|
||||
setup(
|
||||
version=__version__,
|
||||
author="Tiramisu's team",
|
||||
author_email='gnunux@gnunux.info',
|
||||
name=PACKAGE_NAME,
|
||||
description="command-line parser using Tiramisu.",
|
||||
name='tiramisu_cmdline_parser',
|
||||
version=tiramisu_cmdline_parser.__version__,
|
||||
packages=find_packages(),
|
||||
author="Emmanuel Garette & Tiramisu Team",
|
||||
description="command-line parser using Tiramisu.",
|
||||
long_description="""
|
||||
Python3 parser for command-line options and arguments using Tiramisu engine.
|
||||
""",
|
||||
include_package_data=True,
|
||||
url='https://framagit.org/tiramisu/tiramisu-cmdline-parser',
|
||||
license='GNU Library or Lesser General Public License (LGPL)',
|
||||
install_requires=["tiramisu>=5.0"],
|
||||
classifiers=[
|
||||
"Programming Language :: Python :: 3",
|
||||
"License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)",
|
||||
"Operating System :: OS Independent",
|
||||
"Natural Language :: English",
|
||||
"Natural Language :: French",
|
||||
],
|
||||
long_description="""\
|
||||
tiramisu-cmdline-parser
|
||||
---------------------------------
|
||||
|
||||
Python3 parser for command-line options and arguments using Tiramisu engine.
|
||||
""",
|
||||
include_package_data=True,
|
||||
packages=find_packages(include=['tiramisu_cmdline_parser'])
|
||||
classifiers=[
|
||||
"Programming Language :: Python",
|
||||
"Development Status :: 1 - Planning",
|
||||
"License :: LGPLv3",
|
||||
"Natural Language :: French",
|
||||
"Operating System :: OS Independent",
|
||||
"Programming Language :: Python :: 3",
|
||||
"Topic :: Communications",
|
||||
],
|
||||
)
|
||||
|
|
|
|||
193
test/test_readme.py
Normal file
193
test/test_readme.py
Normal file
|
|
@ -0,0 +1,193 @@
|
|||
from io import StringIO
|
||||
from contextlib import redirect_stdout, redirect_stderr
|
||||
|
||||
|
||||
from tiramisu_cmdline_parser import TiramisuCmdlineParser
|
||||
from tiramisu import IntOption, StrOption, BoolOption, ChoiceOption, \
|
||||
SymLinkOption, OptionDescription, Config
|
||||
|
||||
|
||||
def get_config():
|
||||
choiceoption = ChoiceOption('cmd',
|
||||
'choice the sub argument',
|
||||
('str', 'list', 'int', 'none'),
|
||||
properties=('mandatory',
|
||||
'positional'))
|
||||
booloption = BoolOption('verbosity',
|
||||
'increase output verbosity',
|
||||
default=False)
|
||||
short_booloption = SymLinkOption('v', booloption)
|
||||
str_ = StrOption('str',
|
||||
'string option',
|
||||
properties=('mandatory',),
|
||||
requires=[{'option': choiceoption,
|
||||
'expected': 'str',
|
||||
'action': 'disabled',
|
||||
'inverse': True}])
|
||||
list_ = StrOption('list',
|
||||
'list string option',
|
||||
multi=True,
|
||||
properties=('mandatory',),
|
||||
requires=[{'option': choiceoption,
|
||||
'expected': 'list',
|
||||
'action': 'disabled',
|
||||
'inverse': True}])
|
||||
int_ = IntOption('int',
|
||||
'int option',
|
||||
properties=('mandatory',),
|
||||
requires=[{'option': choiceoption,
|
||||
'expected': 'int',
|
||||
'action': 'disabled',
|
||||
'inverse': True}])
|
||||
config = Config(OptionDescription('root',
|
||||
'root',
|
||||
[choiceoption,
|
||||
booloption,
|
||||
short_booloption,
|
||||
str_,
|
||||
list_,
|
||||
int_
|
||||
]))
|
||||
config.property.read_write()
|
||||
return config
|
||||
|
||||
def test_readme_help():
|
||||
output = """usage: prog.py [-h] [-v] {str,list,int,none}
|
||||
|
||||
positional arguments:
|
||||
{str,list,int,none} choice the sub argument
|
||||
|
||||
optional arguments:
|
||||
-h, --help show this help message and exit
|
||||
-v, --verbosity increase output verbosity
|
||||
"""
|
||||
parser = TiramisuCmdlineParser(get_config(), 'prog.py')
|
||||
f = StringIO()
|
||||
with redirect_stdout(f):
|
||||
parser.print_help()
|
||||
assert f.getvalue() == output
|
||||
|
||||
|
||||
def test_readme_positional_mandatory():
|
||||
output = """usage: prog.py [-h] [-v] {str,list,int,none}
|
||||
prog.py: error: the following arguments are required: cmd
|
||||
"""
|
||||
parser = TiramisuCmdlineParser(get_config(), 'prog.py')
|
||||
f = StringIO()
|
||||
with redirect_stderr(f):
|
||||
try:
|
||||
parser.parse_args([])
|
||||
except SystemExit as err:
|
||||
assert str(err) == "2"
|
||||
else:
|
||||
raise Exception('must raises')
|
||||
assert f.getvalue() == output
|
||||
|
||||
|
||||
def test_readme_mandatory():
|
||||
output = """usage: prog.py [-h] [-v] --str STR {str,list,int,none}
|
||||
prog.py: error: the following arguments are required: --str
|
||||
"""
|
||||
parser = TiramisuCmdlineParser(get_config(), 'prog.py')
|
||||
f = StringIO()
|
||||
with redirect_stderr(f):
|
||||
try:
|
||||
parser.parse_args(['str'])
|
||||
except SystemExit as err:
|
||||
assert str(err) == "2"
|
||||
else:
|
||||
raise Exception('must raises')
|
||||
assert f.getvalue() == output
|
||||
|
||||
|
||||
def test_readme_cross():
|
||||
output = """usage: prog.py [-h] [-v] {str,list,int,none}
|
||||
prog.py: error: unrecognized arguments: --int
|
||||
"""
|
||||
parser = TiramisuCmdlineParser(get_config(), 'prog.py')
|
||||
f = StringIO()
|
||||
with redirect_stderr(f):
|
||||
try:
|
||||
parser.parse_args(['none', '--int'])
|
||||
except SystemExit as err:
|
||||
assert str(err) == "2"
|
||||
else:
|
||||
raise Exception('must raises')
|
||||
assert f.getvalue() == output
|
||||
|
||||
|
||||
def test_readme_int():
|
||||
output = {'cmd': 'int',
|
||||
'int': 3,
|
||||
'verbosity': False,
|
||||
'v': False}
|
||||
config = get_config()
|
||||
parser = TiramisuCmdlineParser(config, 'prog.py')
|
||||
parser.parse_args(['int', '--int', '3'])
|
||||
# assert config.value.dict() == output
|
||||
|
||||
|
||||
def test_readme_int_verbosity():
|
||||
output = {'cmd': 'int',
|
||||
'int': 3,
|
||||
'verbosity': True,
|
||||
'v': True}
|
||||
config = get_config()
|
||||
parser = TiramisuCmdlineParser(config, 'prog.py')
|
||||
parser.parse_args(['int', '--int', '3', '--verbosity'])
|
||||
assert config.value.dict() == output
|
||||
|
||||
|
||||
def test_readme_int_verbosity_short():
|
||||
output = {'cmd': 'int',
|
||||
'int': 3,
|
||||
'verbosity': True,
|
||||
'v': True}
|
||||
config = get_config()
|
||||
parser = TiramisuCmdlineParser(config, 'prog.py')
|
||||
parser.parse_args(['int', '--int', '3', '-v'])
|
||||
assert config.value.dict() == output
|
||||
|
||||
|
||||
def test_readme_str():
|
||||
output = {'cmd': 'str',
|
||||
'str': 'value',
|
||||
'verbosity': False,
|
||||
'v': False}
|
||||
config = get_config()
|
||||
parser = TiramisuCmdlineParser(config, 'prog.py')
|
||||
parser.parse_args(['str', '--str', 'value'])
|
||||
assert config.value.dict() == output
|
||||
|
||||
|
||||
def test_readme_str_int():
|
||||
output = {'cmd': 'str',
|
||||
'str': '3',
|
||||
'verbosity': False,
|
||||
'v': False}
|
||||
config = get_config()
|
||||
parser = TiramisuCmdlineParser(config, 'prog.py')
|
||||
parser.parse_args(['str', '--str', '3'])
|
||||
assert config.value.dict() == output
|
||||
|
||||
|
||||
def test_readme_list():
|
||||
output = {'cmd': 'list',
|
||||
'list': ['a', 'b', 'c'],
|
||||
'verbosity': False,
|
||||
'v': False}
|
||||
config = get_config()
|
||||
parser = TiramisuCmdlineParser(config, 'prog.py')
|
||||
parser.parse_args(['list', '--list', 'a', 'b', 'c'])
|
||||
assert config.value.dict() == output
|
||||
|
||||
|
||||
def test_readme_list_uniq():
|
||||
output = {'cmd': 'list',
|
||||
'list': ['a'],
|
||||
'verbosity': False,
|
||||
'v': False}
|
||||
config = get_config()
|
||||
parser = TiramisuCmdlineParser(config, 'prog.py')
|
||||
parser.parse_args(['list', '--list', 'a'])
|
||||
assert config.value.dict() == output
|
||||
|
|
@ -1,196 +0,0 @@
|
|||
from io import StringIO
|
||||
from contextlib import redirect_stdout, redirect_stderr
|
||||
import pytest
|
||||
|
||||
|
||||
from tiramisu_cmdline_parser import TiramisuCmdlineParser
|
||||
from tiramisu import ChoiceOption, OptionDescription, Config
|
||||
try:
|
||||
from tiramisu_api import Config as JsonConfig
|
||||
#params = ['tiramisu', 'tiramisu-json']
|
||||
params = ['tiramisu']
|
||||
except:
|
||||
params = ['tiramisu']
|
||||
|
||||
from .utils import TestHelpFormatter, to_dict
|
||||
|
||||
|
||||
def get_config(json):
|
||||
positional = ChoiceOption('positional',
|
||||
'choice the sub argument',
|
||||
('str', 'list', 'int', 'none'),
|
||||
properties=('positional', 'mandatory'))
|
||||
positional_int = ChoiceOption('positional_int',
|
||||
'choice the sub argument',
|
||||
(1, 2, 3),
|
||||
properties=('positional', 'mandatory'))
|
||||
str_ = ChoiceOption('str',
|
||||
'choice the sub argument',
|
||||
('str1', 'str2', 'str3'))
|
||||
int_ = ChoiceOption('int',
|
||||
'choice the sub argument',
|
||||
(1, 2, 3))
|
||||
int_multi = ChoiceOption('int_multi',
|
||||
'choice the sub argument',
|
||||
(1, 2, 3),
|
||||
multi=True)
|
||||
od = OptionDescription('od',
|
||||
'od',
|
||||
[positional, positional_int, str_, int_, int_multi])
|
||||
config = Config(od)
|
||||
config.property.read_write()
|
||||
if json == 'tiramisu':
|
||||
return config
|
||||
jconfig = JsonConfig(config.option.get())
|
||||
return jconfig
|
||||
|
||||
|
||||
@pytest.fixture(params=params)
|
||||
def json(request):
|
||||
return request.param
|
||||
|
||||
|
||||
def test_choice_positional(json):
|
||||
output1 = '''usage: prog.py "str" "1" [-h] [--str {str1,str2,str3}] [--int {1,2,3}] [--int_multi [{1,2,3} ...]] {str,list,int,none} {1,2,3}
|
||||
prog.py: error: argument positional: invalid choice: 'error' (choose from 'str', 'list', 'int', 'none')
|
||||
'''
|
||||
output2 = '''usage: prog.py "str" "1" [-h] [--str {str1,str2,str3}] [--int {1,2,3}] [--int_multi [{1,2,3} ...]] {str,list,int,none} {1,2,3}
|
||||
prog.py: error: argument positional_int: invalid choice: '4' (choose from '1', '2', '3')
|
||||
'''
|
||||
config = get_config(json)
|
||||
parser = TiramisuCmdlineParser(config, 'prog.py', formatter_class=TestHelpFormatter)
|
||||
parser.parse_args(['str', '1'])
|
||||
assert to_dict(config.value.get()) == {'positional': 'str',
|
||||
'positional_int': 1,
|
||||
'str': None,
|
||||
'int': None,
|
||||
'int_multi': []}
|
||||
f = StringIO()
|
||||
with redirect_stderr(f):
|
||||
try:
|
||||
parser.parse_args(['error', '1'])
|
||||
except SystemExit as err:
|
||||
assert str(err) == "2"
|
||||
else:
|
||||
raise Exception('must raises')
|
||||
assert f.getvalue() == output1
|
||||
|
||||
f = StringIO()
|
||||
with redirect_stderr(f):
|
||||
try:
|
||||
parser.parse_args(['str', '4'])
|
||||
except SystemExit as err:
|
||||
assert str(err) == "2"
|
||||
else:
|
||||
raise Exception('must raises')
|
||||
assert f.getvalue() == output2
|
||||
|
||||
|
||||
def test_choice_str(json):
|
||||
output = """usage: prog.py "str" "1" --str "str3" [-h] [--str {str1,str2,str3}] [--int {1,2,3}] [--int_multi [{1,2,3} ...]] {str,list,int,none} {1,2,3}
|
||||
prog.py: error: argument --str: invalid choice: 'error' (choose from 'str1', 'str2', 'str3')
|
||||
"""
|
||||
config = get_config(json)
|
||||
parser = TiramisuCmdlineParser(config, 'prog.py', formatter_class=TestHelpFormatter)
|
||||
parser.parse_args(['str', '1', '--str', 'str1'])
|
||||
assert to_dict(config.value.get()) == {'positional': 'str',
|
||||
'positional_int': 1,
|
||||
'str': 'str1',
|
||||
'int': None,
|
||||
'int_multi': []}
|
||||
parser.parse_args(['str', '1', '--str', 'str2'])
|
||||
assert to_dict(config.value.get()) == {'positional': 'str',
|
||||
'positional_int': 1,
|
||||
'str': 'str2',
|
||||
'int': None,
|
||||
'int_multi': []}
|
||||
parser.parse_args(['str', '1', '--str', 'str3'])
|
||||
assert to_dict(config.value.get()) == {'positional': 'str',
|
||||
'positional_int': 1,
|
||||
'str': 'str3',
|
||||
'int': None,
|
||||
'int_multi': []}
|
||||
f = StringIO()
|
||||
with redirect_stderr(f):
|
||||
try:
|
||||
parser.parse_args(['str', '1', '--str', 'error'])
|
||||
except SystemExit as err:
|
||||
assert str(err) == "2"
|
||||
else:
|
||||
raise Exception('must raises')
|
||||
assert f.getvalue() == output
|
||||
assert to_dict(config.value.get()) == {'positional': 'str',
|
||||
'positional_int': 1,
|
||||
'str': 'str3',
|
||||
'int': None,
|
||||
'int_multi': []}
|
||||
|
||||
|
||||
def test_choice_int(json):
|
||||
output = """usage: prog.py "str" "1" --int "1" [-h] [--str {str1,str2,str3}] [--int {1,2,3}] [--int_multi [{1,2,3} ...]] {str,list,int,none} {1,2,3}
|
||||
prog.py: error: argument --int: invalid choice: '4' (choose from '1', '2', '3')
|
||||
"""
|
||||
config = get_config(json)
|
||||
parser = TiramisuCmdlineParser(config, 'prog.py', formatter_class=TestHelpFormatter)
|
||||
parser.parse_args(['str', '1', '--int', '1'])
|
||||
assert to_dict(config.value.get()) == {'positional': 'str',
|
||||
'positional_int': 1,
|
||||
'str': None,
|
||||
'int': 1,
|
||||
'int_multi': []}
|
||||
f = StringIO()
|
||||
with redirect_stderr(f):
|
||||
try:
|
||||
parser.parse_args(['str', '1', '--int', '4'])
|
||||
except SystemExit as err:
|
||||
assert str(err) == "2"
|
||||
else:
|
||||
raise Exception('must raises')
|
||||
assert f.getvalue() == output
|
||||
assert to_dict(config.value.get()) == {'positional': 'str',
|
||||
'positional_int': 1,
|
||||
'str': None,
|
||||
'int': 1,
|
||||
'int_multi': []}
|
||||
|
||||
|
||||
def test_choice_int_multi(json):
|
||||
output = """usage: prog.py "str" "1" --int_multi "1" "2" [-h] [--str {str1,str2,str3}] [--int {1,2,3}] [--int_multi [{1,2,3} ...]] {str,list,int,none} {1,2,3}
|
||||
prog.py: error: argument --int_multi: invalid choice: '4' (choose from '1', '2', '3')
|
||||
"""
|
||||
config = get_config(json)
|
||||
parser = TiramisuCmdlineParser(config, 'prog.py', formatter_class=TestHelpFormatter)
|
||||
parser.parse_args(['str', '1', '--int_multi', '1', '2'])
|
||||
assert to_dict(config.value.get()) == {'positional': 'str',
|
||||
'positional_int': 1,
|
||||
'str': None,
|
||||
'int': None,
|
||||
'int_multi': [1, 2]}
|
||||
f = StringIO()
|
||||
with redirect_stderr(f):
|
||||
try:
|
||||
parser.parse_args(['str', '1', '--int_multi', '4'])
|
||||
except SystemExit as err:
|
||||
assert str(err) == "2"
|
||||
else:
|
||||
raise Exception('must raises')
|
||||
assert f.getvalue() == output
|
||||
assert to_dict(config.value.get()) == {'positional': 'str',
|
||||
'positional_int': 1,
|
||||
'str': None,
|
||||
'int': None,
|
||||
'int_multi': [1, 2]}
|
||||
f = StringIO()
|
||||
with redirect_stderr(f):
|
||||
try:
|
||||
parser.parse_args(['str', '1', '--int_multi', '1', '4'])
|
||||
except SystemExit as err:
|
||||
assert str(err) == "2"
|
||||
else:
|
||||
raise Exception('must raises')
|
||||
assert f.getvalue() == output
|
||||
assert to_dict(config.value.get()) == {'positional': 'str',
|
||||
'positional_int': 1,
|
||||
'str': None,
|
||||
'int': None,
|
||||
'int_multi': [1, 2]}
|
||||
|
|
@ -1,95 +0,0 @@
|
|||
from io import StringIO
|
||||
from contextlib import redirect_stdout, redirect_stderr
|
||||
import pytest
|
||||
from argparse import RawDescriptionHelpFormatter
|
||||
|
||||
|
||||
from tiramisu_cmdline_parser import TiramisuCmdlineParser
|
||||
from tiramisu import IntOption, StrOption, BoolOption, ChoiceOption, \
|
||||
OptionDescription, Config
|
||||
try:
|
||||
from tiramisu_api import Config as JsonConfig
|
||||
#params = ['tiramisu', 'tiramisu-json']
|
||||
params = ['tiramisu']
|
||||
except:
|
||||
params = ['tiramisu']
|
||||
from .utils import TestHelpFormatter
|
||||
|
||||
|
||||
|
||||
def get_config(json):
|
||||
choiceoption = ChoiceOption('cmd',
|
||||
'choice the sub argument',
|
||||
('str', 'list', 'int', 'none'),
|
||||
properties=('mandatory',
|
||||
'positional'))
|
||||
od = OptionDescription('od',
|
||||
'od',
|
||||
[choiceoption])
|
||||
root = OptionDescription('root',
|
||||
'root',
|
||||
[od])
|
||||
config = Config(root)
|
||||
config.property.read_write()
|
||||
if json == 'tiramisu':
|
||||
return config
|
||||
jconfig = JsonConfig(config.option.dict())
|
||||
return jconfig
|
||||
|
||||
|
||||
@pytest.fixture(params=params)
|
||||
def json(request):
|
||||
return request.param
|
||||
|
||||
|
||||
def test_help(json):
|
||||
output = """usage: prog.py [-h] {str,list,int,none}
|
||||
|
||||
options:
|
||||
-h, --help show this help message and exit
|
||||
|
||||
od:
|
||||
{str,list,int,none} choice the sub argument
|
||||
"""
|
||||
parser = TiramisuCmdlineParser(get_config(json), 'prog.py', formatter_class=TestHelpFormatter)
|
||||
f = StringIO()
|
||||
with redirect_stdout(f):
|
||||
parser.print_help()
|
||||
assert f.getvalue() == output
|
||||
|
||||
|
||||
def test_help_epilog(json):
|
||||
output = """usage: prog.py [-h] {str,list,int,none}
|
||||
|
||||
options:
|
||||
-h, --help show this help message and exit
|
||||
|
||||
od:
|
||||
{str,list,int,none} choice the sub argument
|
||||
|
||||
two line
|
||||
"""
|
||||
parser = TiramisuCmdlineParser(get_config(json), 'prog.py', epilog="\ntwo\nline", formatter_class=TestHelpFormatter)
|
||||
f = StringIO()
|
||||
with redirect_stdout(f):
|
||||
parser.print_help()
|
||||
assert f.getvalue() == output
|
||||
|
||||
|
||||
def test_help_epilog_raw(json):
|
||||
output = """usage: prog.py [-h] {str,list,int,none}
|
||||
|
||||
options:
|
||||
-h, --help show this help message and exit
|
||||
|
||||
od:
|
||||
{str,list,int,none} choice the sub argument
|
||||
|
||||
two
|
||||
line
|
||||
"""
|
||||
parser = TiramisuCmdlineParser(get_config(json), 'prog.py', epilog="\ntwo\nline", formatter_class=RawDescriptionHelpFormatter)
|
||||
f = StringIO()
|
||||
with redirect_stdout(f):
|
||||
parser.print_help()
|
||||
assert f.getvalue() == output
|
||||
|
|
@ -1,376 +0,0 @@
|
|||
from io import StringIO
|
||||
from contextlib import redirect_stdout, redirect_stderr
|
||||
import pytest
|
||||
|
||||
|
||||
from tiramisu_cmdline_parser import TiramisuCmdlineParser
|
||||
from tiramisu import IntOption, StrOption, BoolOption, ChoiceOption, \
|
||||
OptionDescription, Leadership, Config, submulti
|
||||
try:
|
||||
from tiramisu_api import Config as JsonConfig
|
||||
# params = ['tiramisu', 'tiramisu-json']
|
||||
params = ['tiramisu']
|
||||
except:
|
||||
params = ['tiramisu']
|
||||
|
||||
from .utils import TestHelpFormatter, to_dict
|
||||
|
||||
|
||||
def get_config(json, with_mandatory=False):
|
||||
leader = StrOption('leader', "Leader var", ['192.168.0.1'], multi=True)
|
||||
follower = StrOption('follower', "Follower", multi=True)
|
||||
if with_mandatory:
|
||||
properties = ('mandatory',)
|
||||
else:
|
||||
properties = None
|
||||
follower_submulti = StrOption('follower_submulti', "Follower submulti", multi=submulti, properties=properties)
|
||||
follower_integer = IntOption('follower_integer', "Follower integer", multi=True)
|
||||
follower_boolean = BoolOption('follower_boolean', "Follower boolean", multi=True)
|
||||
follower_choice = ChoiceOption('follower_choice', "Follower choice", ('opt1', 'opt2'), multi=True)
|
||||
opt_list = [leader, follower, follower_submulti, follower_integer, follower_boolean, follower_choice]
|
||||
if with_mandatory:
|
||||
opt_list.append(StrOption('follower_mandatory', "Follower mandatory", multi=True, properties=('mandatory',)))
|
||||
leadership = Leadership('leader', 'leader', opt_list)
|
||||
config = Config(OptionDescription('root', 'root', [leadership]))
|
||||
if json == 'tiramisu':
|
||||
return config
|
||||
jconfig = JsonConfig(config.option.dict())
|
||||
return jconfig
|
||||
|
||||
|
||||
@pytest.fixture(params=params)
|
||||
def json(request):
|
||||
return request.param
|
||||
|
||||
|
||||
def test_leadership_help(json):
|
||||
output = """usage: prog.py [-h] [--leader.leader [LEADER ...]] [--leader.pop-leader INDEX] [--leader.follower INDEX [FOLLOWER]] --leader.follower_submulti INDEX [FOLLOWER_SUBMULTI ...] [--leader.follower_integer INDEX [FOLLOWER_INTEGER]] [--leader.follower_boolean INDEX] [--leader.no-follower_boolean INDEX] [--leader.follower_choice INDEX [{opt1,opt2}]] --leader.follower_mandatory INDEX FOLLOWER_MANDATORY
|
||||
|
||||
options:
|
||||
-h, --help show this help message and exit
|
||||
|
||||
leader:
|
||||
--leader.leader [LEADER ...]
|
||||
Leader var
|
||||
--leader.pop-leader INDEX
|
||||
--leader.follower INDEX [FOLLOWER]
|
||||
Follower
|
||||
--leader.follower_submulti INDEX [FOLLOWER_SUBMULTI ...]
|
||||
Follower submulti
|
||||
--leader.follower_integer INDEX [FOLLOWER_INTEGER]
|
||||
Follower integer
|
||||
--leader.follower_boolean INDEX
|
||||
Follower boolean
|
||||
--leader.no-follower_boolean INDEX
|
||||
--leader.follower_choice INDEX [{opt1,opt2}]
|
||||
Follower choice
|
||||
--leader.follower_mandatory INDEX FOLLOWER_MANDATORY
|
||||
Follower mandatory
|
||||
"""
|
||||
parser = TiramisuCmdlineParser(get_config(json, with_mandatory=True), 'prog.py', formatter_class=TestHelpFormatter)
|
||||
f = StringIO()
|
||||
with redirect_stdout(f):
|
||||
parser.print_help()
|
||||
assert f.getvalue() == output
|
||||
|
||||
|
||||
def test_leadership_modif_leader(json):
|
||||
output = {'leader.leader': ['192.168.1.1'],
|
||||
'leader.follower': [None],
|
||||
'leader.follower_boolean': [None],
|
||||
'leader.follower_choice': [None],
|
||||
'leader.follower_integer': [None],
|
||||
'leader.follower_submulti': [[]]}
|
||||
|
||||
config = get_config(json)
|
||||
parser = TiramisuCmdlineParser(config, 'prog.py')
|
||||
parser.parse_args(['--leader.leader', '192.168.1.1'])
|
||||
assert to_dict(config.value.get()) == output
|
||||
|
||||
|
||||
def test_leadership_modif_follower(json):
|
||||
output = {'leader.leader': ['192.168.0.1'],
|
||||
'leader.follower': ['255.255.255.0'],
|
||||
'leader.follower_boolean': [None],
|
||||
'leader.follower_choice': [None],
|
||||
'leader.follower_integer': [None],
|
||||
'leader.follower_submulti': [[]]}
|
||||
|
||||
config = get_config(json)
|
||||
parser = TiramisuCmdlineParser(config, 'prog.py')
|
||||
parser.parse_args(['--leader.follower', '0', '255.255.255.0'])
|
||||
assert to_dict(config.value.get()) == output
|
||||
|
||||
|
||||
def test_leadership_modif_follower_not_submulti(json):
|
||||
output = """usage: prog.py [-h] [--leader.leader [LEADER ...]] [--leader.pop-leader INDEX] [--leader.follower INDEX [FOLLOWER]] [--leader.follower_submulti INDEX [FOLLOWER_SUBMULTI ...]] [--leader.follower_integer INDEX [FOLLOWER_INTEGER]] [--leader.follower_boolean INDEX] [--leader.no-follower_boolean INDEX] [--leader.follower_choice INDEX [{opt1,opt2}]]
|
||||
prog.py: error: unrecognized arguments: 255.255.255.0
|
||||
"""
|
||||
|
||||
config = get_config(json)
|
||||
parser = TiramisuCmdlineParser(config, 'prog.py', formatter_class=TestHelpFormatter)
|
||||
f = StringIO()
|
||||
with redirect_stderr(f):
|
||||
try:
|
||||
parser.parse_args(['--leader.follower', '0', '255.255.255.0', '255.255.255.0'])
|
||||
except SystemExit as err:
|
||||
assert str(err) == "2"
|
||||
else:
|
||||
raise Exception('must raises')
|
||||
assert f.getvalue() == output
|
||||
|
||||
|
||||
def test_leadership_modif_follower_submulti(json):
|
||||
output = {'leader.leader': ['192.168.0.1'],
|
||||
'leader.follower': [None],
|
||||
'leader.follower_boolean': [None],
|
||||
'leader.follower_choice': [None],
|
||||
'leader.follower_integer': [None],
|
||||
'leader.follower_submulti': [['255.255.255.0']]}
|
||||
|
||||
config = get_config(json)
|
||||
parser = TiramisuCmdlineParser(config, 'prog.py')
|
||||
parser.parse_args(['--leader.follower_submulti', '0', '255.255.255.0'])
|
||||
assert to_dict(config.value.get()) == output
|
||||
|
||||
|
||||
def test_leadership_modif_follower_submulti_multi(json):
|
||||
output = {'leader.leader': ['192.168.0.1'],
|
||||
'leader.follower': [None],
|
||||
'leader.follower_boolean': [None],
|
||||
'leader.follower_choice': [None],
|
||||
'leader.follower_integer': [None],
|
||||
'leader.follower_submulti': [['255.255.255.0', '255.255.255.128']]}
|
||||
|
||||
config = get_config(json)
|
||||
parser = TiramisuCmdlineParser(config, 'prog.py')
|
||||
parser.parse_args(['--leader.follower_submulti', '0', '255.255.255.0', '255.255.255.128'])
|
||||
assert to_dict(config.value.get()) == output
|
||||
|
||||
|
||||
def test_leadership_modif_follower_bool_true(json):
|
||||
output = {'leader.leader': ['192.168.0.1'],
|
||||
'leader.follower': [None],
|
||||
'leader.follower_boolean': [True],
|
||||
'leader.follower_choice': [None],
|
||||
'leader.follower_integer': [None],
|
||||
'leader.follower_submulti': [[]]}
|
||||
|
||||
config = get_config(json)
|
||||
parser = TiramisuCmdlineParser(config, 'prog.py')
|
||||
parser.parse_args(['--leader.follower_boolean', '0'])
|
||||
assert to_dict(config.value.get()) == output
|
||||
|
||||
|
||||
def test_leadership_modif_follower_bool_false(json):
|
||||
output = {'leader.leader': ['192.168.0.1'],
|
||||
'leader.follower': [None],
|
||||
'leader.follower_boolean': [False],
|
||||
'leader.follower_choice': [None],
|
||||
'leader.follower_integer': [None],
|
||||
'leader.follower_submulti': [[]]}
|
||||
|
||||
config = get_config(json)
|
||||
parser = TiramisuCmdlineParser(config, 'prog.py')
|
||||
parser.parse_args(['--leader.no-follower_boolean', '0'])
|
||||
assert to_dict(config.value.get()) == output
|
||||
|
||||
|
||||
def test_leadership_modif_follower_bool_true_fullname(json):
|
||||
output = {'leader.leader': ['192.168.0.1'],
|
||||
'leader.follower': [None],
|
||||
'leader.follower_boolean': [True],
|
||||
'leader.follower_choice': [None],
|
||||
'leader.follower_integer': [None],
|
||||
'leader.follower_submulti': [[]]}
|
||||
|
||||
config = get_config(json)
|
||||
parser = TiramisuCmdlineParser(config, 'prog.py', fullpath=False)
|
||||
parser.parse_args(['--follower_boolean', '0'])
|
||||
assert to_dict(config.value.get()) == output
|
||||
|
||||
|
||||
def test_leadership_modif_follower_bool_false_fullname(json):
|
||||
output = {'leader.leader': ['192.168.0.1'],
|
||||
'leader.follower': [None],
|
||||
'leader.follower_boolean': [False],
|
||||
'leader.follower_choice': [None],
|
||||
'leader.follower_integer': [None],
|
||||
'leader.follower_submulti': [[]]}
|
||||
|
||||
config = get_config(json)
|
||||
parser = TiramisuCmdlineParser(config, 'prog.py', fullpath=False)
|
||||
parser.parse_args(['--no-follower_boolean', '0'])
|
||||
assert to_dict(config.value.get()) == output
|
||||
|
||||
|
||||
def test_leadership_modif_follower_choice(json):
|
||||
output = {'leader.leader': ['192.168.0.1'],
|
||||
'leader.follower': [None],
|
||||
'leader.follower_boolean': [None],
|
||||
'leader.follower_choice': ['opt1'],
|
||||
'leader.follower_integer': [None],
|
||||
'leader.follower_submulti': [[]]}
|
||||
|
||||
config = get_config(json)
|
||||
parser = TiramisuCmdlineParser(config, 'prog.py')
|
||||
parser.parse_args(['--leader.follower_choice', '0', 'opt1'])
|
||||
assert to_dict(config.value.get()) == output
|
||||
|
||||
|
||||
def test_leadership_modif_follower_choice_unknown(json):
|
||||
output = """usage: prog.py [-h] [--leader.leader [LEADER ...]] [--leader.pop-leader INDEX] [--leader.follower INDEX [FOLLOWER]] [--leader.follower_submulti INDEX [FOLLOWER_SUBMULTI ...]] [--leader.follower_integer INDEX [FOLLOWER_INTEGER]] [--leader.follower_boolean INDEX] [--leader.no-follower_boolean INDEX] [--leader.follower_choice INDEX [{opt1,opt2}]]
|
||||
prog.py: error: argument --leader.follower_choice: invalid choice: 'opt_unknown' (choose from 'opt1', 'opt2')
|
||||
"""
|
||||
config = get_config(json)
|
||||
parser = TiramisuCmdlineParser(config, 'prog.py', formatter_class=TestHelpFormatter)
|
||||
f = StringIO()
|
||||
with redirect_stderr(f):
|
||||
try:
|
||||
parser.parse_args(['--leader.follower_choice', '0', 'opt_unknown'])
|
||||
except SystemExit as err:
|
||||
assert str(err) == "2"
|
||||
else:
|
||||
raise Exception('must raises')
|
||||
assert f.getvalue() == output
|
||||
|
||||
|
||||
def test_leadership_modif_follower_not_number(json):
|
||||
output = """usage: prog.py [-h] [--leader.leader [LEADER ...]] [--leader.pop-leader INDEX] [--leader.follower INDEX [FOLLOWER]] [--leader.follower_submulti INDEX [FOLLOWER_SUBMULTI ...]] [--leader.follower_integer INDEX [FOLLOWER_INTEGER]] [--leader.follower_boolean INDEX] [--leader.no-follower_boolean INDEX] [--leader.follower_choice INDEX [{opt1,opt2}]]
|
||||
prog.py: error: index must be a number, not a
|
||||
"""
|
||||
|
||||
config = get_config(json)
|
||||
parser = TiramisuCmdlineParser(config, 'prog.py', formatter_class=TestHelpFormatter)
|
||||
f = StringIO()
|
||||
with redirect_stderr(f):
|
||||
try:
|
||||
parser.parse_args(['--leader.follower', 'a', '255.255.255.0'])
|
||||
except SystemExit as err:
|
||||
assert str(err) == "2"
|
||||
else:
|
||||
raise Exception('must raises')
|
||||
assert f.getvalue() == output
|
||||
|
||||
|
||||
def test_leadership_modif_multi(json):
|
||||
output = {'leader.leader': ['192.168.1.1', '10.253.10.1', '192.168.253.1'],
|
||||
'leader.follower': ['255.255.255.128', None, '255.255.255.0'],
|
||||
'leader.follower_boolean': [None, None, None],
|
||||
'leader.follower_choice': [None, None, None],
|
||||
'leader.follower_integer': [None, None, None],
|
||||
'leader.follower_submulti': [[], [], []]}
|
||||
|
||||
config = get_config(json)
|
||||
parser = TiramisuCmdlineParser(config, 'prog.py')
|
||||
parser.parse_args(['--leader.leader', '192.168.1.1', '10.253.10.1', '192.168.253.1',
|
||||
'--leader.follower', '0', '255.255.255.128',
|
||||
'--leader.follower', '2', '255.255.255.0'])
|
||||
assert to_dict(config.value.get()) == output
|
||||
|
||||
|
||||
def test_leadership_modif_multi_reduce(json):
|
||||
output = {'leader.leader': ['192.168.1.1', '192.168.253.1'],
|
||||
'leader.follower': ['255.255.255.128', '255.255.255.0'],
|
||||
'leader.follower_boolean': [None, None],
|
||||
'leader.follower_choice': [None, None],
|
||||
'leader.follower_integer': [None, None],
|
||||
'leader.follower_submulti': [[], []]}
|
||||
|
||||
config = get_config(json)
|
||||
parser = TiramisuCmdlineParser(config, 'prog.py')
|
||||
parser.parse_args(['--leader.leader', '192.168.1.1', '10.253.10.1', '192.168.253.1',
|
||||
'--leader.follower', '0', '255.255.255.128',
|
||||
'--leader.follower', '2', '255.255.255.0',
|
||||
'--leader.pop-leader', '1'])
|
||||
assert to_dict(config.value.get()) == output
|
||||
|
||||
|
||||
def test_leadership_modif_mandatory(json):
|
||||
output = {'leader.leader': ['192.168.1.1'],
|
||||
'leader.follower': [None],
|
||||
'leader.follower_mandatory': ['255.255.255.128'],
|
||||
'leader.follower_boolean': [None],
|
||||
'leader.follower_choice': [None],
|
||||
'leader.follower_integer': [None],
|
||||
'leader.follower_submulti': [['255.255.255.128']]}
|
||||
output2 = """usage: prog.py --leader.leader "192.168.1.1" [-h] [--leader.leader [LEADER ...]] [--leader.pop-leader INDEX] [--leader.follower INDEX [FOLLOWER]] --leader.follower_submulti INDEX [FOLLOWER_SUBMULTI ...] [--leader.follower_integer INDEX [FOLLOWER_INTEGER]] [--leader.follower_boolean INDEX] [--leader.no-follower_boolean INDEX] [--leader.follower_choice INDEX [{opt1,opt2}]] --leader.follower_mandatory INDEX FOLLOWER_MANDATORY
|
||||
prog.py: error: the following arguments are required: --leader.follower_submulti"""
|
||||
|
||||
config = get_config(json, with_mandatory=True)
|
||||
parser = TiramisuCmdlineParser(config, 'prog.py', formatter_class=TestHelpFormatter)
|
||||
f = StringIO()
|
||||
with redirect_stderr(f):
|
||||
try:
|
||||
parser.parse_args(['--leader.leader', '192.168.1.1'])
|
||||
except SystemExit as err:
|
||||
assert str(err) == "2"
|
||||
else:
|
||||
raise Exception('must raises')
|
||||
assert f.getvalue() == output2 + ', --leader.follower_mandatory\n'
|
||||
f = StringIO()
|
||||
with redirect_stderr(f):
|
||||
try:
|
||||
parser.parse_args(['--leader.leader', '192.168.1.1',
|
||||
'--leader.follower_mandatory', '0', '255.255.255.128'])
|
||||
except SystemExit as err:
|
||||
assert str(err) == "2"
|
||||
else:
|
||||
raise Exception('must raises')
|
||||
assert f.getvalue() == output2 + '\n'
|
||||
parser.parse_args(['--leader.leader', '192.168.1.1',
|
||||
'--leader.follower_submulti', '0', '255.255.255.128',
|
||||
'--leader.follower_mandatory', '0', '255.255.255.128'])
|
||||
assert to_dict(config.value.get()) == output
|
||||
|
||||
|
||||
def test_leadership_modif_mandatory_remove(json):
|
||||
output = {'leader.leader': ['192.168.1.1'],
|
||||
'leader.follower': [None],
|
||||
'leader.follower_mandatory': ['255.255.255.128'],
|
||||
'leader.follower_boolean': [None],
|
||||
'leader.follower_choice': [None],
|
||||
'leader.follower_integer': [None],
|
||||
'leader.follower_submulti': [['255.255.255.128']]}
|
||||
output2 = """usage: prog.py --leader.leader "192.168.1.1" [-h] [--leader.pop-leader INDEX] [--leader.follower INDEX [FOLLOWER]] --leader.follower_submulti INDEX [FOLLOWER_SUBMULTI ...] [--leader.follower_integer INDEX [FOLLOWER_INTEGER]] [--leader.follower_boolean INDEX] [--leader.no-follower_boolean INDEX] [--leader.follower_choice INDEX [{opt1,opt2}]] --leader.follower_mandatory INDEX FOLLOWER_MANDATORY
|
||||
prog.py: error: the following arguments are required: --leader.follower_submulti"""
|
||||
|
||||
config = get_config(json, with_mandatory=True)
|
||||
parser = TiramisuCmdlineParser(config, 'prog.py', display_modified_value=False, formatter_class=TestHelpFormatter)
|
||||
f = StringIO()
|
||||
with redirect_stderr(f):
|
||||
try:
|
||||
parser.parse_args(['--leader.leader', '192.168.1.1'])
|
||||
except SystemExit as err:
|
||||
assert str(err) == "2"
|
||||
else:
|
||||
raise Exception('must raises')
|
||||
assert f.getvalue() == output2 + ', --leader.follower_mandatory\n'
|
||||
f = StringIO()
|
||||
with redirect_stderr(f):
|
||||
try:
|
||||
parser.parse_args(['--leader.leader', '192.168.1.1',
|
||||
'--leader.follower_mandatory', '0', '255.255.255.128'])
|
||||
except SystemExit as err:
|
||||
assert str(err) == "2"
|
||||
else:
|
||||
raise Exception('must raises')
|
||||
assert f.getvalue() == output2 + '\n'
|
||||
parser.parse_args(['--leader.leader', '192.168.1.1',
|
||||
'--leader.follower_submulti', '0', '255.255.255.128',
|
||||
'--leader.follower_mandatory', '0', '255.255.255.128'])
|
||||
assert to_dict(config.value.get()) == output
|
||||
|
||||
|
||||
def test_leadership_modif_mandatory_unvalidate(json):
|
||||
output = {'leader.leader': ['192.168.1.1'],
|
||||
'leader.follower': [None],
|
||||
'leader.follower_mandatory': [None],
|
||||
'leader.follower_boolean': [None],
|
||||
'leader.follower_choice': [None],
|
||||
'leader.follower_integer': [None],
|
||||
'leader.follower_submulti': [[]]}
|
||||
config = get_config(json, with_mandatory=True)
|
||||
parser = TiramisuCmdlineParser(config, 'prog.py')
|
||||
parser.parse_args(['--leader.leader', '192.168.1.1'], valid_mandatory=False)
|
||||
assert to_dict(config.value.get()) == output
|
||||
|
|
@ -1,188 +0,0 @@
|
|||
from io import StringIO
|
||||
from contextlib import redirect_stdout, redirect_stderr
|
||||
import pytest
|
||||
|
||||
|
||||
from tiramisu_cmdline_parser import TiramisuCmdlineParser
|
||||
from tiramisu import IntOption, StrOption, BoolOption, ChoiceOption, \
|
||||
SymLinkOption, OptionDescription, Config
|
||||
try:
|
||||
from tiramisu_api import Config as JsonConfig
|
||||
#params = ['tiramisu', 'tiramisu-json']
|
||||
params = ['tiramisu']
|
||||
except:
|
||||
params = ['tiramisu']
|
||||
from .utils import TestHelpFormatter
|
||||
|
||||
|
||||
def get_config(json, has_tree=False, default_verbosity=False, add_long=False, add_store_false=False, empty_optiondescription=False):
|
||||
choiceoption = ChoiceOption('cmd',
|
||||
'choice the sub argument',
|
||||
('str', 'list', 'int', 'none'),
|
||||
properties=('mandatory',
|
||||
'positional'))
|
||||
booloption = BoolOption('verbosity',
|
||||
'increase output verbosity',
|
||||
default=default_verbosity)
|
||||
short_booloption = SymLinkOption('v', booloption)
|
||||
|
||||
od0 = OptionDescription('od0',
|
||||
'Sub-Tree 1',
|
||||
[choiceoption,
|
||||
booloption,
|
||||
short_booloption,
|
||||
])
|
||||
if empty_optiondescription:
|
||||
descr = None
|
||||
else:
|
||||
descr = 'First OptionDescription'
|
||||
od1 = OptionDescription('od1',
|
||||
descr,
|
||||
[od0])
|
||||
before = StrOption('before',
|
||||
'Before',
|
||||
properties=('mandatory',))
|
||||
after = StrOption('after',
|
||||
'After',
|
||||
properties=('mandatory',))
|
||||
str_ = StrOption('str',
|
||||
'string option 2',
|
||||
properties=('mandatory',))
|
||||
subtree = OptionDescription('subtree',
|
||||
'Sub-Tree 2',
|
||||
[str_])
|
||||
od2 = OptionDescription('od2',
|
||||
None,
|
||||
[before, subtree, after])
|
||||
root = OptionDescription('root',
|
||||
'root',
|
||||
[od1, od2])
|
||||
config = Config(root)
|
||||
config.property.read_write()
|
||||
if json == 'tiramisu':
|
||||
return config
|
||||
jconfig = JsonConfig(config.option.dict())
|
||||
return jconfig
|
||||
|
||||
|
||||
@pytest.fixture(params=params)
|
||||
def json(request):
|
||||
return request.param
|
||||
|
||||
|
||||
def test_optiondescription_help(json):
|
||||
output = """usage: prog.py [-h] [-v] [-nv] --od2.subtree.str STR --od2.before BEFORE --od2.after AFTER {str,list,int,none}
|
||||
|
||||
options:
|
||||
-h, --help show this help message and exit
|
||||
|
||||
od1:
|
||||
First OptionDescription
|
||||
|
||||
od1.od0:
|
||||
Sub-Tree 1
|
||||
|
||||
{str,list,int,none} choice the sub argument
|
||||
-v, --od1.od0.verbosity
|
||||
increase output verbosity
|
||||
-nv, --od1.od0.no-verbosity
|
||||
|
||||
od2:
|
||||
--od2.before BEFORE Before
|
||||
--od2.after AFTER After
|
||||
|
||||
od2.subtree:
|
||||
Sub-Tree 2
|
||||
|
||||
--od2.subtree.str STR
|
||||
string option 2
|
||||
"""
|
||||
parser = TiramisuCmdlineParser(get_config(json), 'prog.py', formatter_class=TestHelpFormatter)
|
||||
f = StringIO()
|
||||
with redirect_stdout(f):
|
||||
parser.print_help()
|
||||
assert f.getvalue() == output
|
||||
|
||||
|
||||
def test_optiondescription_help_remove_empty_od(json):
|
||||
output = """usage: prog.py [-h] [-v] [-nv] --od2.subtree.str STR --od2.before BEFORE --od2.after AFTER {str,list,int,none}
|
||||
|
||||
options:
|
||||
-h, --help show this help message and exit
|
||||
|
||||
od1.od0:
|
||||
Sub-Tree 1
|
||||
|
||||
{str,list,int,none} choice the sub argument
|
||||
-v, --od1.od0.verbosity
|
||||
increase output verbosity
|
||||
-nv, --od1.od0.no-verbosity
|
||||
|
||||
od2:
|
||||
--od2.before BEFORE Before
|
||||
--od2.after AFTER After
|
||||
|
||||
od2.subtree:
|
||||
Sub-Tree 2
|
||||
|
||||
--od2.subtree.str STR
|
||||
string option 2
|
||||
"""
|
||||
parser = TiramisuCmdlineParser(get_config(json), 'prog.py', remove_empty_od=True, formatter_class=TestHelpFormatter)
|
||||
f = StringIO()
|
||||
with redirect_stdout(f):
|
||||
parser.print_help()
|
||||
assert f.getvalue() == output
|
||||
|
||||
|
||||
def test_optiondescription_help_remove_empty_description_od(json):
|
||||
output = """usage: prog.py [-h] [-v] [-nv] --od2.subtree.str STR --od2.before BEFORE --od2.after AFTER {str,list,int,none}
|
||||
|
||||
options:
|
||||
-h, --help show this help message and exit
|
||||
|
||||
od1.od0:
|
||||
Sub-Tree 1
|
||||
|
||||
{str,list,int,none} choice the sub argument
|
||||
-v, --od1.od0.verbosity
|
||||
increase output verbosity
|
||||
-nv, --od1.od0.no-verbosity
|
||||
|
||||
od2:
|
||||
--od2.before BEFORE Before
|
||||
--od2.after AFTER After
|
||||
|
||||
od2.subtree:
|
||||
Sub-Tree 2
|
||||
|
||||
--od2.subtree.str STR
|
||||
string option 2
|
||||
"""
|
||||
parser = TiramisuCmdlineParser(get_config(json, empty_optiondescription=True), 'prog.py', formatter_class=TestHelpFormatter)
|
||||
f = StringIO()
|
||||
with redirect_stdout(f):
|
||||
parser.print_help()
|
||||
assert f.getvalue() == output
|
||||
|
||||
|
||||
def test_optiondescription_help_subtree(json):
|
||||
output = """usage: prog.py [-h] --od2.subtree.str STR --od2.before BEFORE --od2.after AFTER
|
||||
|
||||
options:
|
||||
-h, --help show this help message and exit
|
||||
--od2.before BEFORE Before
|
||||
--od2.after AFTER After
|
||||
|
||||
od2.subtree:
|
||||
Sub-Tree 2
|
||||
|
||||
--od2.subtree.str STR
|
||||
string option 2
|
||||
"""
|
||||
config = get_config(json)
|
||||
parser = TiramisuCmdlineParser(config, 'prog.py', root='od2', formatter_class=TestHelpFormatter)
|
||||
f = StringIO()
|
||||
with redirect_stdout(f):
|
||||
parser.print_help()
|
||||
assert f.getvalue() == output
|
||||
|
|
@ -1,901 +0,0 @@
|
|||
from io import StringIO
|
||||
from contextlib import redirect_stdout, redirect_stderr
|
||||
import pytest
|
||||
|
||||
|
||||
from tiramisu_cmdline_parser import TiramisuCmdlineParser
|
||||
from tiramisu import IntOption, StrOption, BoolOption, ChoiceOption, \
|
||||
SymLinkOption, OptionDescription, Config, calc_value, \
|
||||
Calculation, ParamValue, ParamOption, Params
|
||||
try:
|
||||
from tiramisu_api import Config as JsonConfig
|
||||
#params = ['tiramisu', 'tiramisu-json']
|
||||
params = ['tiramisu']
|
||||
except:
|
||||
params = ['tiramisu']
|
||||
from .utils import TestHelpFormatter, to_dict
|
||||
|
||||
|
||||
def get_config(json, has_tree=False, default_verbosity=False, add_long=False, add_store_false=False):
|
||||
choiceoption = ChoiceOption('cmd',
|
||||
'choice the sub argument',
|
||||
('str', 'list', 'int', 'none'),
|
||||
properties=('mandatory',
|
||||
'positional'))
|
||||
booloption = BoolOption('verbosity',
|
||||
'increase output verbosity',
|
||||
default=default_verbosity)
|
||||
short_booloption = SymLinkOption('v', booloption)
|
||||
str_ = StrOption('str',
|
||||
'string option',
|
||||
properties=('mandatory',
|
||||
Calculation(calc_value,
|
||||
Params(ParamValue('disabled'),
|
||||
kwargs={'condition': ParamOption(choiceoption),
|
||||
'reverse_condition': ParamValue(True),
|
||||
'expected': ParamValue('str')})),
|
||||
),
|
||||
)
|
||||
list_ = StrOption('list',
|
||||
'list string option',
|
||||
multi=True,
|
||||
properties=('mandatory',
|
||||
Calculation(calc_value,
|
||||
Params(ParamValue('disabled'),
|
||||
kwargs={'condition': ParamOption(choiceoption),
|
||||
'reverse_condition': ParamValue(True),
|
||||
'expected': ParamValue('list')})),
|
||||
),
|
||||
)
|
||||
int_ = IntOption('int',
|
||||
'int option',
|
||||
properties=('mandatory',
|
||||
Calculation(calc_value,
|
||||
Params(ParamValue('disabled'),
|
||||
kwargs={'condition': ParamOption(choiceoption),
|
||||
'reverse_condition': ParamValue(True),
|
||||
'expected': ParamValue('int')})),
|
||||
),
|
||||
)
|
||||
|
||||
root = OptionDescription('root',
|
||||
'root',
|
||||
[choiceoption,
|
||||
booloption,
|
||||
short_booloption,
|
||||
str_,
|
||||
list_,
|
||||
int_
|
||||
])
|
||||
if has_tree:
|
||||
root = OptionDescription('root',
|
||||
'root',
|
||||
[root])
|
||||
config = Config(root)
|
||||
config.property.read_write()
|
||||
if add_store_false:
|
||||
config.option('verbosity').property.add('storefalse')
|
||||
if add_long:
|
||||
config.option('verbosity').property.add('longargument')
|
||||
if json == 'tiramisu':
|
||||
return config
|
||||
jconfig = JsonConfig(config.option.dict())
|
||||
return jconfig
|
||||
|
||||
|
||||
@pytest.fixture(params=params)
|
||||
def json(request):
|
||||
return request.param
|
||||
|
||||
|
||||
def test_readme_help(json):
|
||||
output = """usage: prog.py [-h] [-v] [-nv] {str,list,int,none}
|
||||
|
||||
positional arguments:
|
||||
{str,list,int,none} choice the sub argument
|
||||
|
||||
options:
|
||||
-h, --help show this help message and exit
|
||||
-v, --verbosity increase output verbosity
|
||||
-nv, --no-verbosity
|
||||
"""
|
||||
parser = TiramisuCmdlineParser(get_config(json), 'prog.py', formatter_class=TestHelpFormatter)
|
||||
f = StringIO()
|
||||
with redirect_stdout(f):
|
||||
parser.print_help()
|
||||
assert f.getvalue() == output
|
||||
|
||||
|
||||
def test_readme_help_tree(json):
|
||||
output = """usage: prog.py [-h] [-v] [-nv] {str,list,int,none}
|
||||
|
||||
options:
|
||||
-h, --help show this help message and exit
|
||||
|
||||
root:
|
||||
{str,list,int,none} choice the sub argument
|
||||
-v, --root.verbosity increase output verbosity
|
||||
-nv, --root.no-verbosity
|
||||
"""
|
||||
parser = TiramisuCmdlineParser(get_config(json, True), 'prog.py', formatter_class=TestHelpFormatter)
|
||||
f = StringIO()
|
||||
with redirect_stdout(f):
|
||||
parser.print_help()
|
||||
assert f.getvalue() == output
|
||||
|
||||
|
||||
def test_readme_help_tree_flatten(json):
|
||||
output = """usage: prog.py [-h] [-v] [-nv] {str,list,int,none}
|
||||
|
||||
options:
|
||||
-h, --help show this help message and exit
|
||||
|
||||
root:
|
||||
{str,list,int,none} choice the sub argument
|
||||
-v, --verbosity increase output verbosity
|
||||
-nv, --no-verbosity
|
||||
"""
|
||||
parser = TiramisuCmdlineParser(get_config(json, True), 'prog.py', fullpath=False, formatter_class=TestHelpFormatter)
|
||||
f = StringIO()
|
||||
with redirect_stdout(f):
|
||||
parser.print_help()
|
||||
assert f.getvalue() == output
|
||||
|
||||
|
||||
def test_readme_help_modif_positional(json):
|
||||
output = """usage: prog.py "str" [-h] [-v] [-nv] --str STR {str,list,int,none}
|
||||
|
||||
positional arguments:
|
||||
{str,list,int,none} choice the sub argument
|
||||
|
||||
options:
|
||||
-h, --help show this help message and exit
|
||||
-v, --verbosity increase output verbosity
|
||||
-nv, --no-verbosity
|
||||
--str STR string option
|
||||
"""
|
||||
parser = TiramisuCmdlineParser(get_config(json), 'prog.py', formatter_class=TestHelpFormatter)
|
||||
f = StringIO()
|
||||
with redirect_stdout(f):
|
||||
try:
|
||||
parser.parse_args(['str', '--help'])
|
||||
except SystemExit as err:
|
||||
assert str(err) == "0"
|
||||
else:
|
||||
raise Exception('must raises')
|
||||
assert f.getvalue() == output
|
||||
|
||||
|
||||
def test_readme_help_modif_positional_remove(json):
|
||||
output = """usage: prog.py "str" [-h] [-v] [-nv] --str STR
|
||||
|
||||
options:
|
||||
-h, --help show this help message and exit
|
||||
-v, --verbosity increase output verbosity
|
||||
-nv, --no-verbosity
|
||||
--str STR string option
|
||||
"""
|
||||
parser = TiramisuCmdlineParser(get_config(json), 'prog.py', display_modified_value=False, formatter_class=TestHelpFormatter)
|
||||
f = StringIO()
|
||||
with redirect_stdout(f):
|
||||
try:
|
||||
parser.parse_args(['str', '--help'])
|
||||
except SystemExit as err:
|
||||
assert str(err) == "0"
|
||||
else:
|
||||
raise Exception('must raises')
|
||||
assert f.getvalue() == output
|
||||
|
||||
|
||||
def test_readme_help_modif(json):
|
||||
output = """usage: prog.py "str" --str "toto" [-h] [-v] [-nv] --str STR {str,list,int,none}
|
||||
|
||||
positional arguments:
|
||||
{str,list,int,none} choice the sub argument
|
||||
|
||||
options:
|
||||
-h, --help show this help message and exit
|
||||
-v, --verbosity increase output verbosity
|
||||
-nv, --no-verbosity
|
||||
--str STR string option
|
||||
"""
|
||||
parser = TiramisuCmdlineParser(get_config(json), 'prog.py', formatter_class=TestHelpFormatter)
|
||||
f = StringIO()
|
||||
with redirect_stdout(f):
|
||||
try:
|
||||
parser.parse_args(['str', '--str', 'toto', '--help'])
|
||||
except SystemExit as err:
|
||||
assert str(err) == "0"
|
||||
else:
|
||||
raise Exception('must raises')
|
||||
assert f.getvalue() == output
|
||||
|
||||
|
||||
def test_readme_help_modif_remove(json):
|
||||
output = """usage: prog.py "str" --str "toto" [-h] [-v] [-nv]
|
||||
|
||||
options:
|
||||
-h, --help show this help message and exit
|
||||
-v, --verbosity increase output verbosity
|
||||
-nv, --no-verbosity
|
||||
"""
|
||||
parser = TiramisuCmdlineParser(get_config(json), 'prog.py', display_modified_value=False, formatter_class=TestHelpFormatter)
|
||||
f = StringIO()
|
||||
with redirect_stdout(f):
|
||||
try:
|
||||
parser.parse_args(['str', '--str', 'toto', '--help'])
|
||||
except SystemExit as err:
|
||||
assert str(err) == "0"
|
||||
else:
|
||||
raise Exception('must raises')
|
||||
assert f.getvalue() == output
|
||||
|
||||
|
||||
def test_readme_help_modif_short(json):
|
||||
output = """usage: prog.py "str" -v [-h] [-v] [-nv] --str STR {str,list,int,none}
|
||||
|
||||
positional arguments:
|
||||
{str,list,int,none} choice the sub argument
|
||||
|
||||
options:
|
||||
-h, --help show this help message and exit
|
||||
-v, --verbosity increase output verbosity
|
||||
-nv, --no-verbosity
|
||||
--str STR string option
|
||||
"""
|
||||
parser = TiramisuCmdlineParser(get_config(json), 'prog.py', formatter_class=TestHelpFormatter)
|
||||
f = StringIO()
|
||||
with redirect_stdout(f):
|
||||
try:
|
||||
parser.parse_args(['str', '-v', '--help'])
|
||||
except SystemExit as err:
|
||||
assert str(err) == "0"
|
||||
else:
|
||||
raise Exception('must raises')
|
||||
assert f.getvalue() == output
|
||||
|
||||
|
||||
def test_readme_help_modif_short_remove(json):
|
||||
# FIXME -v -nv ?? pas de description
|
||||
output = """usage: prog.py "str" -v [-h] [-nv] --str STR
|
||||
|
||||
options:
|
||||
-h, --help show this help message and exit
|
||||
-nv, --no-verbosity increase output verbosity
|
||||
--str STR string option
|
||||
"""
|
||||
parser = TiramisuCmdlineParser(get_config(json), 'prog.py', display_modified_value=False, formatter_class=TestHelpFormatter)
|
||||
f = StringIO()
|
||||
with redirect_stdout(f):
|
||||
try:
|
||||
parser.parse_args(['str', '-v', '--help'])
|
||||
except SystemExit as err:
|
||||
assert str(err) == "0"
|
||||
else:
|
||||
raise Exception('must raises')
|
||||
assert f.getvalue() == output
|
||||
|
||||
|
||||
def test_readme_help_modif_short_no1(json):
|
||||
output = """usage: prog.py "str" -v [-h] [-v] [-nv] --str STR {str,list,int,none}
|
||||
|
||||
positional arguments:
|
||||
{str,list,int,none} choice the sub argument
|
||||
|
||||
options:
|
||||
-h, --help show this help message and exit
|
||||
-v, --verbosity increase output verbosity
|
||||
-nv, --no-verbosity
|
||||
--str STR string option
|
||||
"""
|
||||
parser = TiramisuCmdlineParser(get_config(json), 'prog.py', formatter_class=TestHelpFormatter)
|
||||
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_help_modif_short_no_remove(json):
|
||||
output = """usage: prog.py "str" -v [-h] [-v] --str STR
|
||||
|
||||
options:
|
||||
-h, --help show this help message and exit
|
||||
-v, --verbosity increase output verbosity
|
||||
--str STR string option
|
||||
"""
|
||||
parser = TiramisuCmdlineParser(get_config(json), 'prog.py', display_modified_value=False, formatter_class=TestHelpFormatter)
|
||||
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(json):
|
||||
output = """usage: prog.py [-h] [-v] [-nv] {str,list,int,none}
|
||||
prog.py: error: the following arguments are required: cmd
|
||||
"""
|
||||
parser = TiramisuCmdlineParser(get_config(json), 'prog.py', formatter_class=TestHelpFormatter)
|
||||
f = StringIO()
|
||||
with redirect_stderr(f):
|
||||
try:
|
||||
parser.parse_args([])
|
||||
except SystemExit as err:
|
||||
assert str(err) == "2"
|
||||
else:
|
||||
raise Exception('must raises')
|
||||
assert f.getvalue() == output
|
||||
|
||||
|
||||
def test_readme_positional_mandatory_tree(json):
|
||||
output = """usage: prog.py [-h] [-v] [-nv] {str,list,int,none}
|
||||
prog.py: error: the following arguments are required: root.cmd
|
||||
"""
|
||||
parser = TiramisuCmdlineParser(get_config(json, True), 'prog.py', formatter_class=TestHelpFormatter)
|
||||
f = StringIO()
|
||||
with redirect_stderr(f):
|
||||
try:
|
||||
parser.parse_args([])
|
||||
except SystemExit as err:
|
||||
assert str(err) == "2"
|
||||
else:
|
||||
raise Exception('must raises')
|
||||
assert f.getvalue() == output
|
||||
|
||||
|
||||
def test_readme_positional_mandatory_tree_flatten(json):
|
||||
output = """usage: prog.py [-h] [-v] [-nv] {str,list,int,none}
|
||||
prog.py: error: the following arguments are required: cmd
|
||||
"""
|
||||
parser = TiramisuCmdlineParser(get_config(json, True), 'prog.py', fullpath=False, formatter_class=TestHelpFormatter)
|
||||
f = StringIO()
|
||||
with redirect_stderr(f):
|
||||
try:
|
||||
parser.parse_args([])
|
||||
except SystemExit as err:
|
||||
assert str(err) == "2"
|
||||
else:
|
||||
raise Exception('must raises')
|
||||
assert f.getvalue() == output
|
||||
|
||||
|
||||
def test_readme_mandatory(json):
|
||||
output = """usage: prog.py "str" [-h] [-v] [-nv] --str STR {str,list,int,none}
|
||||
prog.py: error: the following arguments are required: --str
|
||||
"""
|
||||
parser = TiramisuCmdlineParser(get_config(json), 'prog.py', formatter_class=TestHelpFormatter)
|
||||
f = StringIO()
|
||||
with redirect_stderr(f):
|
||||
try:
|
||||
parser.parse_args(['str'])
|
||||
except SystemExit as err:
|
||||
assert str(err) == "2"
|
||||
else:
|
||||
raise Exception('must raises')
|
||||
assert f.getvalue() == output
|
||||
|
||||
|
||||
def test_readme_mandatory_remove(json):
|
||||
output = """usage: prog.py "str" [-h] [-v] [-nv] --str STR
|
||||
prog.py: error: the following arguments are required: --str
|
||||
"""
|
||||
parser = TiramisuCmdlineParser(get_config(json), 'prog.py', display_modified_value=False, formatter_class=TestHelpFormatter)
|
||||
f = StringIO()
|
||||
with redirect_stderr(f):
|
||||
try:
|
||||
parser.parse_args(['str'])
|
||||
except SystemExit as err:
|
||||
assert str(err) == "2"
|
||||
else:
|
||||
raise Exception('must raises')
|
||||
assert f.getvalue() == output
|
||||
|
||||
|
||||
def test_readme_mandatory_tree(json):
|
||||
output = """usage: prog.py "str" [-h] [-v] [-nv] --root.str STR {str,list,int,none}
|
||||
prog.py: error: the following arguments are required: --root.str
|
||||
"""
|
||||
parser = TiramisuCmdlineParser(get_config(json, True), 'prog.py', formatter_class=TestHelpFormatter)
|
||||
f = StringIO()
|
||||
with redirect_stderr(f):
|
||||
try:
|
||||
parser.parse_args(['str'])
|
||||
except SystemExit as err:
|
||||
assert str(err) == "2"
|
||||
else:
|
||||
raise Exception('must raises')
|
||||
assert f.getvalue() == output
|
||||
|
||||
|
||||
def test_readme_mandatory_tree_remove(json):
|
||||
output = """usage: prog.py "str" [-h] [-v] [-nv] --root.str STR
|
||||
prog.py: error: the following arguments are required: --root.str
|
||||
"""
|
||||
parser = TiramisuCmdlineParser(get_config(json, True), 'prog.py', display_modified_value=False, formatter_class=TestHelpFormatter)
|
||||
f = StringIO()
|
||||
with redirect_stderr(f):
|
||||
try:
|
||||
parser.parse_args(['str'])
|
||||
except SystemExit as err:
|
||||
assert str(err) == "2"
|
||||
else:
|
||||
raise Exception('must raises')
|
||||
assert f.getvalue() == output
|
||||
|
||||
|
||||
def test_readme_mandatory_tree_flatten(json):
|
||||
output = """usage: prog.py "str" [-h] [-v] [-nv] --str STR {str,list,int,none}
|
||||
prog.py: error: the following arguments are required: --str
|
||||
"""
|
||||
parser = TiramisuCmdlineParser(get_config(json, True), 'prog.py', fullpath=False, formatter_class=TestHelpFormatter)
|
||||
f = StringIO()
|
||||
with redirect_stderr(f):
|
||||
try:
|
||||
parser.parse_args(['str'])
|
||||
except SystemExit as err:
|
||||
assert str(err) == "2"
|
||||
else:
|
||||
raise Exception('must raises')
|
||||
assert f.getvalue() == output
|
||||
|
||||
|
||||
def test_readme_mandatory_tree_flatten_remove(json):
|
||||
output = """usage: prog.py "str" [-h] [-v] [-nv] --str STR
|
||||
prog.py: error: the following arguments are required: --str
|
||||
"""
|
||||
parser = TiramisuCmdlineParser(get_config(json, True), 'prog.py', fullpath=False, display_modified_value=False, formatter_class=TestHelpFormatter)
|
||||
f = StringIO()
|
||||
with redirect_stderr(f):
|
||||
try:
|
||||
parser.parse_args(['str'])
|
||||
except SystemExit as err:
|
||||
assert str(err) == "2"
|
||||
else:
|
||||
raise Exception('must raises')
|
||||
assert f.getvalue() == output
|
||||
|
||||
|
||||
def test_readme_cross(json):
|
||||
output = """usage: prog.py "none" [-h] [-v] [-nv] {str,list,int,none}
|
||||
prog.py: error: unrecognized arguments: --int
|
||||
"""
|
||||
parser = TiramisuCmdlineParser(get_config(json), 'prog.py', formatter_class=TestHelpFormatter)
|
||||
f = StringIO()
|
||||
with redirect_stderr(f):
|
||||
try:
|
||||
parser.parse_args(['none', '--int', '1'])
|
||||
except SystemExit as err:
|
||||
assert str(err) == "2"
|
||||
else:
|
||||
raise Exception('must raises')
|
||||
assert f.getvalue() == output
|
||||
|
||||
|
||||
def test_readme_cross_remove(json):
|
||||
output = """usage: prog.py "none" [-h] [-v] [-nv]
|
||||
prog.py: error: unrecognized arguments: --int
|
||||
"""
|
||||
parser = TiramisuCmdlineParser(get_config(json), 'prog.py', display_modified_value=False, formatter_class=TestHelpFormatter)
|
||||
f = StringIO()
|
||||
with redirect_stderr(f):
|
||||
try:
|
||||
parser.parse_args(['none', '--int', '1'])
|
||||
except SystemExit as err:
|
||||
assert str(err) == "2"
|
||||
else:
|
||||
raise Exception('must raises')
|
||||
assert f.getvalue() == output
|
||||
|
||||
|
||||
def test_readme_cross_tree(json):
|
||||
output = """usage: prog.py "none" [-h] [-v] [-nv] {str,list,int,none}
|
||||
prog.py: error: unrecognized arguments: --root.int
|
||||
"""
|
||||
parser = TiramisuCmdlineParser(get_config(json, True), 'prog.py', formatter_class=TestHelpFormatter)
|
||||
f = StringIO()
|
||||
with redirect_stderr(f):
|
||||
try:
|
||||
parser.parse_args(['none', '--root.int', '1'])
|
||||
except SystemExit as err:
|
||||
assert str(err) == "2"
|
||||
else:
|
||||
raise Exception('must raises')
|
||||
assert f.getvalue() == output
|
||||
|
||||
|
||||
def test_readme_cross_tree_remove(json):
|
||||
output = """usage: prog.py "none" [-h] [-v] [-nv]
|
||||
prog.py: error: unrecognized arguments: --root.int
|
||||
"""
|
||||
parser = TiramisuCmdlineParser(get_config(json, True), 'prog.py', display_modified_value=False, formatter_class=TestHelpFormatter)
|
||||
f = StringIO()
|
||||
with redirect_stderr(f):
|
||||
try:
|
||||
parser.parse_args(['none', '--root.int', '1'])
|
||||
except SystemExit as err:
|
||||
assert str(err) == "2"
|
||||
else:
|
||||
raise Exception('must raises')
|
||||
assert f.getvalue() == output
|
||||
|
||||
|
||||
def test_readme_cross_tree_flatten(json):
|
||||
output = """usage: prog.py "none" [-h] [-v] [-nv] {str,list,int,none}
|
||||
prog.py: error: unrecognized arguments: --int
|
||||
"""
|
||||
parser = TiramisuCmdlineParser(get_config(json, True), 'prog.py', fullpath=False, formatter_class=TestHelpFormatter)
|
||||
f = StringIO()
|
||||
with redirect_stderr(f):
|
||||
try:
|
||||
parser.parse_args(['none', '--int', '1'])
|
||||
except SystemExit as err:
|
||||
assert str(err) == "2"
|
||||
else:
|
||||
raise Exception('must raises')
|
||||
assert f.getvalue() == output
|
||||
|
||||
|
||||
def test_readme_cross_tree_flatten_remove(json):
|
||||
output = """usage: prog.py "none" [-h] [-v] [-nv]
|
||||
prog.py: error: unrecognized arguments: --int
|
||||
"""
|
||||
parser = TiramisuCmdlineParser(get_config(json, True), 'prog.py', fullpath=False, display_modified_value=False, formatter_class=TestHelpFormatter)
|
||||
f = StringIO()
|
||||
with redirect_stderr(f):
|
||||
try:
|
||||
parser.parse_args(['none', '--int', '1'])
|
||||
except SystemExit as err:
|
||||
assert str(err) == "2"
|
||||
else:
|
||||
raise Exception('must raises')
|
||||
assert f.getvalue() == output
|
||||
|
||||
|
||||
def test_readme_unknown(json):
|
||||
output = """usage: prog.py [-h] [-v] [-nv] {str,list,int,none}
|
||||
prog.py: error: argument root.cmd: invalid choice: 'unknown' (choose from 'str', 'list', 'int', 'none')
|
||||
"""
|
||||
parser = TiramisuCmdlineParser(get_config(json, True), 'prog.py', fullpath=False, formatter_class=TestHelpFormatter)
|
||||
f = StringIO()
|
||||
with redirect_stderr(f):
|
||||
try:
|
||||
parser.parse_args(['unknown'])
|
||||
except SystemExit as err:
|
||||
assert str(err) == "2"
|
||||
else:
|
||||
raise Exception('must raises')
|
||||
assert f.getvalue() == output
|
||||
|
||||
|
||||
def test_readme_int(json):
|
||||
output = {'cmd': 'int',
|
||||
'int': 3,
|
||||
'verbosity': False,
|
||||
'v': False}
|
||||
config = get_config(json)
|
||||
parser = TiramisuCmdlineParser(config, 'prog.py')
|
||||
parser.parse_args(['int', '--int', '3'])
|
||||
assert to_dict(config.value.get()) == output
|
||||
|
||||
|
||||
def test_readme_int_tree(json):
|
||||
output = {'root.cmd': 'int',
|
||||
'root.int': 3,
|
||||
'root.verbosity': False,
|
||||
'root.v': False}
|
||||
config = get_config(json, True)
|
||||
parser = TiramisuCmdlineParser(config, 'prog.py')
|
||||
parser.parse_args(['int', '--root.int', '3'])
|
||||
assert to_dict(config.value.get()) == output
|
||||
|
||||
|
||||
def test_readme_int_tree_flatten(json):
|
||||
output = {'root.cmd': 'int',
|
||||
'root.int': 3,
|
||||
'root.verbosity': False,
|
||||
'root.v': False}
|
||||
config = get_config(json, True)
|
||||
parser = TiramisuCmdlineParser(config, 'prog.py', fullpath=False)
|
||||
parser.parse_args(['int', '--int', '3'])
|
||||
assert to_dict(config.value.get()) == output
|
||||
|
||||
|
||||
def test_readme_int_verbosity(json):
|
||||
output = {'cmd': 'int',
|
||||
'int': 3,
|
||||
'verbosity': True,
|
||||
'v': True}
|
||||
config = get_config(json)
|
||||
parser = TiramisuCmdlineParser(config, 'prog.py')
|
||||
parser.parse_args(['int', '--int', '3', '--verbosity'])
|
||||
assert to_dict(config.value.get()) == output
|
||||
|
||||
|
||||
def test_readme_int_verbosity_tree(json):
|
||||
output = {'root.cmd': 'int',
|
||||
'root.int': 3,
|
||||
'root.verbosity': True,
|
||||
'root.v': True}
|
||||
config = get_config(json, True)
|
||||
parser = TiramisuCmdlineParser(config, 'prog.py')
|
||||
parser.parse_args(['int', '--root.int', '3', '--root.verbosity'])
|
||||
assert to_dict(config.value.get()) == output
|
||||
|
||||
|
||||
def test_readme_int_verbosity_tree_flatten(json):
|
||||
output = {'root.cmd': 'int',
|
||||
'root.int': 3,
|
||||
'root.verbosity': True,
|
||||
'root.v': True}
|
||||
config = get_config(json, True)
|
||||
parser = TiramisuCmdlineParser(config, 'prog.py', fullpath=False)
|
||||
parser.parse_args(['int', '--int', '3', '--verbosity'])
|
||||
assert to_dict(config.value.get()) == output
|
||||
|
||||
|
||||
def test_readme_int_verbosity_short(json):
|
||||
output = {'cmd': 'int',
|
||||
'int': 3,
|
||||
'verbosity': True,
|
||||
'v': True}
|
||||
config = get_config(json)
|
||||
parser = TiramisuCmdlineParser(config, 'prog.py')
|
||||
parser.parse_args(['int', '--int', '3', '-v'])
|
||||
assert to_dict(config.value.get()) == output
|
||||
|
||||
|
||||
def test_readme_int_verbosity_short_store_false(json):
|
||||
output = {'cmd': 'int',
|
||||
'int': 3,
|
||||
'verbosity': None,
|
||||
'v': True}
|
||||
config = get_config(json, default_verbosity=None, add_store_false=True)
|
||||
parser = TiramisuCmdlineParser(config, 'prog.py')
|
||||
parser.parse_args(['int', '--int', '3', '-v'])
|
||||
output = {'cmd': 'int',
|
||||
'int': 3,
|
||||
'verbosity': False,
|
||||
'v': False}
|
||||
assert to_dict(config.value.get()) == output
|
||||
parser.parse_args(['int', '--int', '3', '-nv'])
|
||||
output = {'cmd': 'int',
|
||||
'int': 3,
|
||||
'verbosity': True,
|
||||
'v': True}
|
||||
assert to_dict(config.value.get()) == output
|
||||
|
||||
|
||||
def test_readme_int_verbosity_short_no(json):
|
||||
output = {'cmd': 'int',
|
||||
'int': 3,
|
||||
'verbosity': False,
|
||||
'v': False}
|
||||
config = get_config(json)
|
||||
parser = TiramisuCmdlineParser(config, 'prog.py')
|
||||
parser.parse_args(['int', '--int', '3', '-nv'])
|
||||
assert to_dict(config.value.get()) == output
|
||||
|
||||
|
||||
def test_readme_int_verbosity_short_tree(json):
|
||||
output = {'root.cmd': 'int',
|
||||
'root.int': 3,
|
||||
'root.verbosity': True,
|
||||
'root.v': True}
|
||||
config = get_config(json, True)
|
||||
parser = TiramisuCmdlineParser(config, 'prog.py')
|
||||
parser.parse_args(['int', '--root.int', '3', '-v'])
|
||||
assert to_dict(config.value.get()) == output
|
||||
|
||||
|
||||
def test_readme_int_verbosity_short_tree_flatten(json):
|
||||
output = {'root.cmd': 'int',
|
||||
'root.int': 3,
|
||||
'root.verbosity': True,
|
||||
'root.v': True}
|
||||
config = get_config(json, True)
|
||||
parser = TiramisuCmdlineParser(config, 'prog.py', fullpath=False)
|
||||
parser.parse_args(['int', '--int', '3', '-v'])
|
||||
assert to_dict(config.value.get()) == output
|
||||
|
||||
|
||||
def test_readme_int_verbosity_short_and_not(json):
|
||||
output = {'cmd': 'int',
|
||||
'int': 3,
|
||||
'verbosity': False,
|
||||
'v': False}
|
||||
config = get_config(json)
|
||||
parser = TiramisuCmdlineParser(config, 'prog.py')
|
||||
parser.parse_args(['int', '--int', '3', '-v', '-nv'])
|
||||
assert to_dict(config.value.get()) == output
|
||||
|
||||
|
||||
def test_readme_str(json):
|
||||
output = {'cmd': 'str',
|
||||
'str': 'value',
|
||||
'verbosity': False,
|
||||
'v': False}
|
||||
config = get_config(json)
|
||||
parser = TiramisuCmdlineParser(config, 'prog.py')
|
||||
parser.parse_args(['str', '--str', 'value'])
|
||||
assert to_dict(config.value.get()) == output
|
||||
|
||||
|
||||
def test_readme_str_tree(json):
|
||||
output = {'root.cmd': 'str',
|
||||
'root.str': 'value',
|
||||
'root.verbosity': False,
|
||||
'root.v': False}
|
||||
config = get_config(json, True)
|
||||
parser = TiramisuCmdlineParser(config, 'prog.py')
|
||||
parser.parse_args(['str', '--root.str', 'value'])
|
||||
assert to_dict(config.value.get()) == output
|
||||
|
||||
|
||||
def test_readme_str_tree_flatten(json):
|
||||
output = {'root.cmd': 'str',
|
||||
'root.str': 'value',
|
||||
'root.verbosity': False,
|
||||
'root.v': False}
|
||||
config = get_config(json, True)
|
||||
parser = TiramisuCmdlineParser(config, 'prog.py', fullpath=False)
|
||||
parser.parse_args(['str', '--str', 'value'])
|
||||
assert to_dict(config.value.get()) == output
|
||||
|
||||
|
||||
def test_readme_str_int(json):
|
||||
output = {'cmd': 'str',
|
||||
'str': '3',
|
||||
'verbosity': False,
|
||||
'v': False}
|
||||
config = get_config(json)
|
||||
parser = TiramisuCmdlineParser(config, 'prog.py')
|
||||
parser.parse_args(['str', '--str', '3'])
|
||||
assert to_dict(config.value.get()) == output
|
||||
|
||||
|
||||
def test_readme_str_int_tree(json):
|
||||
output = {'root.cmd': 'str',
|
||||
'root.str': '3',
|
||||
'root.verbosity': False,
|
||||
'root.v': False}
|
||||
config = get_config(json, True)
|
||||
parser = TiramisuCmdlineParser(config, 'prog.py')
|
||||
parser.parse_args(['str', '--root.str', '3'])
|
||||
assert to_dict(config.value.get()) == output
|
||||
|
||||
|
||||
def test_readme_str_int_tree_flatten(json):
|
||||
output = {'root.cmd': 'str',
|
||||
'root.str': '3',
|
||||
'root.verbosity': False,
|
||||
'root.v': False}
|
||||
config = get_config(json, True)
|
||||
parser = TiramisuCmdlineParser(config, 'prog.py', fullpath=False)
|
||||
parser.parse_args(['str', '--str', '3'])
|
||||
assert to_dict(config.value.get()) == output
|
||||
|
||||
|
||||
def test_readme_list_single(json):
|
||||
output = {'cmd': 'list',
|
||||
'list': ['a'],
|
||||
'verbosity': False,
|
||||
'v': False}
|
||||
config = get_config(json)
|
||||
parser = TiramisuCmdlineParser(config, 'prog.py')
|
||||
parser.parse_args(['list', '--list', 'a'])
|
||||
assert to_dict(config.value.get()) == output
|
||||
|
||||
|
||||
def test_readme_list(json):
|
||||
output = {'cmd': 'list',
|
||||
'list': ['a', 'b', 'c'],
|
||||
'verbosity': False,
|
||||
'v': False}
|
||||
config = get_config(json)
|
||||
parser = TiramisuCmdlineParser(config, 'prog.py')
|
||||
parser.parse_args(['list', '--list', 'a', 'b', 'c'])
|
||||
assert to_dict(config.value.get()) == output
|
||||
|
||||
|
||||
def test_readme_list_tree(json):
|
||||
output = {'root.cmd': 'list',
|
||||
'root.list': ['a', 'b', 'c'],
|
||||
'root.verbosity': False,
|
||||
'root.v': False}
|
||||
config = get_config(json, True)
|
||||
parser = TiramisuCmdlineParser(config, 'prog.py')
|
||||
parser.parse_args(['list', '--root.list', 'a', 'b', 'c'])
|
||||
assert to_dict(config.value.get()) == output
|
||||
|
||||
|
||||
def test_readme_list_tree_flatten(json):
|
||||
output = {'root.cmd': 'list',
|
||||
'root.list': ['a', 'b', 'c'],
|
||||
'root.verbosity': False,
|
||||
'root.v': False}
|
||||
config = get_config(json, True)
|
||||
parser = TiramisuCmdlineParser(config, 'prog.py', fullpath=False)
|
||||
parser.parse_args(['list', '--list', 'a', 'b', 'c'])
|
||||
assert to_dict(config.value.get()) == output
|
||||
|
||||
|
||||
def test_readme_list_uniq(json):
|
||||
output = {'cmd': 'list',
|
||||
'list': ['a'],
|
||||
'verbosity': False,
|
||||
'v': False}
|
||||
config = get_config(json)
|
||||
parser = TiramisuCmdlineParser(config, 'prog.py')
|
||||
parser.parse_args(['list', '--list', 'a'])
|
||||
assert to_dict(config.value.get()) == output
|
||||
|
||||
|
||||
def test_readme_list_uniq_tree(json):
|
||||
output = {'root.cmd': 'list',
|
||||
'root.list': ['a'],
|
||||
'root.verbosity': False,
|
||||
'root.v': False}
|
||||
config = get_config(json, True)
|
||||
parser = TiramisuCmdlineParser(config, 'prog.py')
|
||||
parser.parse_args(['list', '--root.list', 'a'])
|
||||
assert to_dict(config.value.get()) == output
|
||||
|
||||
|
||||
def test_readme_list_uniq_tree_flatten(json):
|
||||
output = {'root.cmd': 'list',
|
||||
'root.list': ['a'],
|
||||
'root.verbosity': False,
|
||||
'root.v': False}
|
||||
config = get_config(json, True)
|
||||
parser = TiramisuCmdlineParser(config, 'prog.py', fullpath=False)
|
||||
parser.parse_args(['list', '--list', 'a'])
|
||||
assert to_dict(config.value.get()) == output
|
||||
|
||||
|
||||
def test_readme_longargument(json):
|
||||
output = {'cmd': 'list',
|
||||
'list': ['a'],
|
||||
'verbosity': True,
|
||||
'v': True}
|
||||
config = get_config(json, add_long=True)
|
||||
parser = TiramisuCmdlineParser(config, 'prog.py')
|
||||
parser.parse_args(['list', '--list', 'a', '--v'])
|
||||
assert to_dict(config.value.get()) == output
|
||||
|
||||
|
||||
def test_readme_unknown_key(json):
|
||||
output1 = """usage: prog.py [-h] [-v] [-nv] {str,list,int,none}
|
||||
prog.py: error: unrecognized arguments: --unknown
|
||||
"""
|
||||
output2 = """usage: prog.py [-h] [-v] [-nv] {str,list,int,none}
|
||||
prog.py: error: unrecognized arguments: --root.unknown
|
||||
"""
|
||||
parser = TiramisuCmdlineParser(get_config(json, True), 'prog.py', fullpath=False, formatter_class=TestHelpFormatter)
|
||||
f = StringIO()
|
||||
with redirect_stderr(f):
|
||||
try:
|
||||
parser.parse_args(['--unknown'])
|
||||
except SystemExit as err:
|
||||
assert str(err) == "2"
|
||||
else:
|
||||
raise Exception('must raises')
|
||||
assert f.getvalue() == output1
|
||||
|
||||
f = StringIO()
|
||||
with redirect_stderr(f):
|
||||
try:
|
||||
parser.parse_args(['--root.unknown'])
|
||||
except SystemExit as err:
|
||||
assert str(err) == "2"
|
||||
else:
|
||||
raise Exception('must raises')
|
||||
assert f.getvalue() == output2
|
||||
|
|
@ -1,211 +0,0 @@
|
|||
from io import StringIO
|
||||
import pytest
|
||||
from contextlib import redirect_stderr
|
||||
|
||||
|
||||
from tiramisu_cmdline_parser import TiramisuCmdlineParser
|
||||
from tiramisu import IntOption, StrOption, BoolOption, ChoiceOption, \
|
||||
SymLinkOption, OptionDescription, Config
|
||||
try:
|
||||
from tiramisu_api import Config as JsonConfig
|
||||
params = ['tiramisu']
|
||||
#params = ['tiramisu', 'tiramisu-json']
|
||||
except:
|
||||
params = ['tiramisu']
|
||||
|
||||
from .utils import to_dict
|
||||
|
||||
|
||||
@pytest.fixture(params=params)
|
||||
def json(request):
|
||||
return request.param
|
||||
|
||||
|
||||
def test_short(json):
|
||||
def get_config():
|
||||
list_ = StrOption('list',
|
||||
'list string option')
|
||||
slist_ = SymLinkOption('l', list_)
|
||||
root = OptionDescription('root',
|
||||
'root',
|
||||
[list_,
|
||||
slist_,
|
||||
])
|
||||
config = Config(root)
|
||||
config.property.read_write()
|
||||
if json != 'tiramisu':
|
||||
config = JsonConfig(config.option.dict())
|
||||
return config
|
||||
#
|
||||
output = {'list': None, 'l': None}
|
||||
config = get_config()
|
||||
parser = TiramisuCmdlineParser(config, 'prog.py')
|
||||
parser.parse_args([])
|
||||
assert to_dict(config.value.get()) == output
|
||||
#
|
||||
output = {'list': 'a', 'l': 'a'}
|
||||
config = get_config()
|
||||
parser = TiramisuCmdlineParser(config, 'prog.py')
|
||||
parser.parse_args(['--list', 'a'])
|
||||
assert to_dict(config.value.get()) == output
|
||||
#
|
||||
output = {'list': 'a', 'l': 'a'}
|
||||
config = get_config()
|
||||
parser = TiramisuCmdlineParser(config, 'prog.py')
|
||||
parser.parse_args(['-l', 'a'])
|
||||
assert to_dict(config.value.get()) == output
|
||||
#
|
||||
assert config.option('list').value.get() == config.option('l').value.get()
|
||||
assert config.option('list').owner.get() == config.option('l').owner.get()
|
||||
assert config.option('list').owner.isdefault() == config.option('l').owner.isdefault()
|
||||
|
||||
|
||||
def test_short_mandatory(json):
|
||||
def get_config():
|
||||
list_ = StrOption('list',
|
||||
'list string option',
|
||||
properties=('mandatory',))
|
||||
slist_ = SymLinkOption('l', list_)
|
||||
root = OptionDescription('root',
|
||||
'root',
|
||||
[list_,
|
||||
slist_,
|
||||
])
|
||||
config = Config(root)
|
||||
config.property.read_write()
|
||||
if json != 'tiramisu':
|
||||
config = JsonConfig(config.option.dict())
|
||||
return config
|
||||
#
|
||||
output = """usage: prog.py [-h] -l LIST
|
||||
prog.py: error: the following arguments are required: --list
|
||||
"""
|
||||
config = get_config()
|
||||
parser = TiramisuCmdlineParser(config, 'prog.py')
|
||||
f = StringIO()
|
||||
with redirect_stderr(f):
|
||||
try:
|
||||
parser.parse_args([])
|
||||
except SystemExit as err:
|
||||
assert str(err) == "2"
|
||||
else:
|
||||
raise Exception('must raises')
|
||||
assert f.getvalue() == output
|
||||
#
|
||||
output = {'list': 'a', 'l': 'a'}
|
||||
config = get_config()
|
||||
parser = TiramisuCmdlineParser(config, 'prog.py')
|
||||
parser.parse_args(['--list', 'a'])
|
||||
assert to_dict(config.value.get()) == output
|
||||
#
|
||||
output = {'list': 'a', 'l': 'a'}
|
||||
config = get_config()
|
||||
parser = TiramisuCmdlineParser(config, 'prog.py')
|
||||
parser.parse_args(['-l', 'a'])
|
||||
assert to_dict(config.value.get()) == output
|
||||
|
||||
|
||||
def test_short_multi(json):
|
||||
def get_config():
|
||||
list_ = StrOption('list',
|
||||
'list string option',
|
||||
multi=True)
|
||||
slist_ = SymLinkOption('l', list_)
|
||||
root = OptionDescription('root',
|
||||
'root',
|
||||
[list_,
|
||||
slist_,
|
||||
])
|
||||
config = Config(root)
|
||||
config.property.read_write()
|
||||
if json != 'tiramisu':
|
||||
config = JsonConfig(config.option.dict())
|
||||
return config
|
||||
#
|
||||
output = {'list': [], 'l': []}
|
||||
config = get_config()
|
||||
parser = TiramisuCmdlineParser(config, 'prog.py')
|
||||
parser.parse_args([])
|
||||
assert to_dict(config.value.get()) == output
|
||||
#
|
||||
output = {'list': ['a'], 'l': ['a']}
|
||||
config = get_config()
|
||||
parser = TiramisuCmdlineParser(config, 'prog.py')
|
||||
parser.parse_args(['--list', 'a'])
|
||||
assert to_dict(config.value.get()) == output
|
||||
#
|
||||
output = {'list': ['a', 'b'], 'l': ['a', 'b']}
|
||||
config = get_config()
|
||||
parser = TiramisuCmdlineParser(config, 'prog.py')
|
||||
parser.parse_args(['--list', 'a', 'b'])
|
||||
assert to_dict(config.value.get()) == output
|
||||
#
|
||||
output = {'list': ['a'], 'l': ['a']}
|
||||
config = get_config()
|
||||
parser = TiramisuCmdlineParser(config, 'prog.py')
|
||||
parser.parse_args(['-l', 'a'])
|
||||
assert to_dict(config.value.get()) == output
|
||||
#
|
||||
output = {'list': ['a', 'b'], 'l': ['a', 'b']}
|
||||
config = get_config()
|
||||
parser = TiramisuCmdlineParser(config, 'prog.py')
|
||||
parser.parse_args(['-l', 'a', 'b'])
|
||||
assert to_dict(config.value.get()) == output
|
||||
|
||||
|
||||
def test_short_multi_mandatory(json):
|
||||
def get_config():
|
||||
list_ = StrOption('list',
|
||||
'list string option',
|
||||
multi=True,
|
||||
properties=('mandatory',))
|
||||
slist_ = SymLinkOption('l', list_)
|
||||
root = OptionDescription('root',
|
||||
'root',
|
||||
[list_,
|
||||
slist_,
|
||||
])
|
||||
config = Config(root)
|
||||
config.property.read_write()
|
||||
if json != 'tiramisu':
|
||||
config = JsonConfig(config.option.dict())
|
||||
return config
|
||||
#
|
||||
output = """usage: prog.py [-h] -l LIST [LIST ...]
|
||||
prog.py: error: the following arguments are required: --list
|
||||
"""
|
||||
config = get_config()
|
||||
parser = TiramisuCmdlineParser(config, 'prog.py')
|
||||
f = StringIO()
|
||||
with redirect_stderr(f):
|
||||
try:
|
||||
parser.parse_args([])
|
||||
except SystemExit as err:
|
||||
assert str(err) == "2"
|
||||
else:
|
||||
raise Exception('must raises')
|
||||
assert f.getvalue() == output
|
||||
#
|
||||
output = {'list': ['a'], 'l': ['a']}
|
||||
config = get_config()
|
||||
parser = TiramisuCmdlineParser(config, 'prog.py')
|
||||
parser.parse_args(['--list', 'a'])
|
||||
assert to_dict(config.value.get()) == output
|
||||
#
|
||||
output = {'list': ['a', 'b'], 'l': ['a', 'b']}
|
||||
config = get_config()
|
||||
parser = TiramisuCmdlineParser(config, 'prog.py')
|
||||
parser.parse_args(['--list', 'a', 'b'])
|
||||
assert to_dict(config.value.get()) == output
|
||||
#
|
||||
output = {'list': ['a'], 'l': ['a']}
|
||||
config = get_config()
|
||||
parser = TiramisuCmdlineParser(config, 'prog.py')
|
||||
parser.parse_args(['-l', 'a'])
|
||||
assert to_dict(config.value.get()) == output
|
||||
#
|
||||
output = {'list': ['a', 'b'], 'l': ['a', 'b']}
|
||||
config = get_config()
|
||||
parser = TiramisuCmdlineParser(config, 'prog.py')
|
||||
parser.parse_args(['-l', 'a', 'b'])
|
||||
assert to_dict(config.value.get()) == output
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
from argparse import HelpFormatter
|
||||
from tiramisu_cmdline_parser.api import TiramisuHelpFormatter
|
||||
|
||||
|
||||
def _leadership_to_dict(dico, ret):
|
||||
leader, *followers = list(dico)
|
||||
ret[leader.path()] = dico[leader]
|
||||
for follower in followers:
|
||||
follower_path = follower.path()
|
||||
ret.setdefault(follower_path, []).append(dico[follower])
|
||||
|
||||
|
||||
def _to_dict(dico, ret):
|
||||
for key, value in dico.items():
|
||||
if key.isoptiondescription():
|
||||
if key.isleadership():
|
||||
_leadership_to_dict(value, ret)
|
||||
else:
|
||||
_to_dict(value, ret)
|
||||
else:
|
||||
ret[key.path()] = value
|
||||
|
||||
|
||||
def to_dict(dico):
|
||||
ret = {}
|
||||
_to_dict(dico, ret)
|
||||
return ret
|
||||
|
||||
|
||||
class TestHelpFormatter(TiramisuHelpFormatter, HelpFormatter):
|
||||
def __init__(self,
|
||||
*args,
|
||||
**kwargs,
|
||||
):
|
||||
return super().__init__(*args, **kwargs, width=5000)
|
||||
|
|
@ -1,9 +1,4 @@
|
|||
try:
|
||||
from .api import TiramisuCmdlineParser
|
||||
except ImportError as err:
|
||||
import warnings
|
||||
warnings.warn("cannot not import TiramisuCmdlineParser {err}", ImportWarning)
|
||||
TiramisuCmdlineParser = None
|
||||
from .tiramisu_cmdline_parser import TiramisuCmdlineParser
|
||||
|
||||
__version__ = "0.5"
|
||||
__version__ = "0.0.1"
|
||||
__all__ = ('TiramisuCmdlineParser',)
|
||||
|
|
|
|||
|
|
@ -1,644 +0,0 @@
|
|||
# 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
|
||||
# Free Software Foundation, either version 3 of the License, or (at your
|
||||
# option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||
# details.
|
||||
#
|
||||
# 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/>.
|
||||
from typing import Union, List, Dict, Tuple, Optional, Any
|
||||
from argparse import ArgumentParser, Namespace, SUPPRESS, _HelpAction, HelpFormatter
|
||||
from copy import copy
|
||||
from gettext import gettext as _
|
||||
|
||||
#try:
|
||||
from tiramisu import Config
|
||||
from tiramisu.error import PropertiesOptionError, LeadershipError
|
||||
#except ImportError:
|
||||
# Config = None
|
||||
# from tiramisu_api.error import PropertiesOptionError
|
||||
# LeadershipError = ValueError
|
||||
try:
|
||||
from tiramisu_api import Config as ConfigJson
|
||||
if Config is None:
|
||||
Config = ConfigJson
|
||||
except ImportError:
|
||||
ConfigJson = Config
|
||||
|
||||
|
||||
def get_choice_list(config, properties, display):
|
||||
def convert(choice):
|
||||
if isinstance(choice, int):
|
||||
return str(choice)
|
||||
return choice
|
||||
choices = [convert(choice) for choice in config.value.list()]
|
||||
if choices and choices[0] == '':
|
||||
del choices[0]
|
||||
if display:
|
||||
choices = '{{{}}}'.format(','.join(choices))
|
||||
if 'mandatory' not in properties:
|
||||
choices = '[{}]'.format(choices)
|
||||
return choices
|
||||
|
||||
|
||||
class TiramisuNamespace(Namespace):
|
||||
def __init__(self,
|
||||
config: Config,
|
||||
root: Optional[str]) -> None:
|
||||
super().__setattr__('_config', config)
|
||||
super().__setattr__('_root', root)
|
||||
super().__setattr__('list_force_no', {})
|
||||
super().__setattr__('list_force_del', {})
|
||||
super().__setattr__('arguments', {})
|
||||
self._populate()
|
||||
super().__init__()
|
||||
|
||||
def _populate(self) -> None:
|
||||
if self._root is None:
|
||||
config = self._config
|
||||
else:
|
||||
config = self._config.option(self._root)
|
||||
self._parse(config.value.get())
|
||||
|
||||
def _parse(self, subconfig):
|
||||
for option, value in subconfig.items():
|
||||
if option.isoptiondescription():
|
||||
self._parse(value)
|
||||
elif not option.issymlinkoption():
|
||||
if value == [] and option.ismulti():
|
||||
value = None
|
||||
super().__setattr__(option.path(), value)
|
||||
|
||||
def __setattr__(self,
|
||||
key: str,
|
||||
value: Any,
|
||||
) -> None:
|
||||
if key in self.list_force_no:
|
||||
true_key = self.list_force_no[key]
|
||||
elif key in self.list_force_del:
|
||||
true_key = self.list_force_del[key]
|
||||
else:
|
||||
true_key = key
|
||||
option = self._config.option(true_key)
|
||||
if option.isfollower():
|
||||
_setattr = self._setattr_follower
|
||||
if not value[0].isdecimal():
|
||||
raise ValueError('index must be a number, not {}'.format(value[0]))
|
||||
index = int(value[0])
|
||||
option = self._config.option(true_key, index)
|
||||
true_value = ','.join(value[1:])
|
||||
else:
|
||||
_setattr = self._setattr
|
||||
true_value = value
|
||||
if 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:
|
||||
if key in self.list_force_del:
|
||||
option.value.pop(value)
|
||||
else:
|
||||
_setattr(option, true_key, key, value)
|
||||
except ValueError as err:
|
||||
if option.type() == 'choice':
|
||||
values = option.value.list()
|
||||
display_value = ''
|
||||
if isinstance(true_value, list):
|
||||
for val in value:
|
||||
if val not in values:
|
||||
display_value = val
|
||||
break
|
||||
else:
|
||||
display_value = true_value
|
||||
choices = get_choice_list(option, option.property.get(), False)
|
||||
raise ValueError("argument {}: invalid choice: '{}' (choose from {})".format(self.arguments[key], display_value, ', '.join([f"'{val}'" for val in choices])))
|
||||
else:
|
||||
raise err
|
||||
|
||||
def _setattr(self,
|
||||
option: 'Option',
|
||||
true_key: str,
|
||||
key: str,
|
||||
value: Any) -> None:
|
||||
if option.ismulti() and \
|
||||
value is not None and \
|
||||
not isinstance(value, list):
|
||||
value = [value]
|
||||
try:
|
||||
option.value.set(value)
|
||||
except PropertiesOptionError:
|
||||
raise AttributeError('unrecognized arguments: {}'.format(self.arguments[key]))
|
||||
|
||||
def _setattr_follower(self,
|
||||
option: 'Option',
|
||||
true_key: str,
|
||||
key: str,
|
||||
value: Any) -> None:
|
||||
index = int(value[0])
|
||||
if option.type() == 'boolean':
|
||||
value = key not in self.list_force_no
|
||||
elif option.issubmulti():
|
||||
value = value[1:]
|
||||
else:
|
||||
value = value[1]
|
||||
self._config.option(true_key, index).value.set(value)
|
||||
|
||||
|
||||
class TiramisuHelpFormatter:
|
||||
def _get_default_metavar_for_optional(self,
|
||||
action):
|
||||
ret = super()._get_default_metavar_for_optional(action)
|
||||
if '.' in ret:
|
||||
ret = ret.rsplit('.', 1)[1]
|
||||
return ret
|
||||
|
||||
class _Section(HelpFormatter._Section):
|
||||
def format_help(self):
|
||||
# Remove empty OD
|
||||
if self.formatter.remove_empty_od and \
|
||||
len(self.items) == 1 and \
|
||||
self.items[0][0].__name__ == '_format_text':
|
||||
return ''
|
||||
return super().format_help()
|
||||
|
||||
|
||||
class _TiramisuHelpAction(_HelpAction):
|
||||
needs = False
|
||||
def __call__(self, *args, **kwargs):
|
||||
_TiramisuHelpAction.needs = True
|
||||
|
||||
def display(self, parser):
|
||||
_HelpAction.__call__(self, parser, None, None)
|
||||
|
||||
|
||||
class _BuildKwargs:
|
||||
def __init__(self,
|
||||
name: str,
|
||||
option: 'Option',
|
||||
cmdlineparser: 'TiramisuCmdlineParser',
|
||||
properties: List[str],
|
||||
force_no: bool,
|
||||
force_del: bool,
|
||||
display_modified_value: bool,
|
||||
not_display: bool) -> None:
|
||||
self.kwargs = {}
|
||||
self.cmdlineparser = cmdlineparser
|
||||
self.properties = properties
|
||||
self.force_no = force_no
|
||||
self.force_del = force_del
|
||||
if (not self.force_no or (not_display and not display_modified_value)) and not self.force_del:
|
||||
description = option.description()
|
||||
if not description:
|
||||
description = description.replace('%', '%%')
|
||||
self.kwargs['help'] = description
|
||||
if 'positional' not in self.properties:
|
||||
is_short_name = self.cmdlineparser._is_short_name(name, 'longargument' in self.properties)
|
||||
if self.force_no:
|
||||
ga_name = self.gen_argument_name(name, is_short_name)
|
||||
ga_path = self.gen_argument_name(option.path(), is_short_name)
|
||||
self.cmdlineparser.namespace.list_force_no[ga_path] = option.path()
|
||||
elif self.force_del:
|
||||
ga_name = self.gen_argument_name(name, is_short_name)
|
||||
ga_path = self.gen_argument_name(option.path(), is_short_name)
|
||||
self.cmdlineparser.namespace.list_force_del[ga_path] = option.path()
|
||||
else:
|
||||
ga_name = name
|
||||
self.kwargs['dest'] = self.gen_argument_name(option.path(), False)
|
||||
argument = self.cmdlineparser._gen_argument(ga_name, is_short_name)
|
||||
self.cmdlineparser.namespace.arguments[option.path()] = argument
|
||||
self.args = [argument]
|
||||
else:
|
||||
self.cmdlineparser.namespace.arguments[option.path()] = option.path()
|
||||
self.args = [option.path()]
|
||||
|
||||
def __setitem__(self,
|
||||
key: str,
|
||||
value: Any) -> None:
|
||||
self.kwargs[key] = value
|
||||
|
||||
def add_argument(self,
|
||||
option: 'Option'):
|
||||
is_short_name = self.cmdlineparser._is_short_name(option.name(), 'longargument' in self.properties)
|
||||
if self.force_no:
|
||||
name = self.gen_argument_name(option.name(), is_short_name)
|
||||
elif self.force_del:
|
||||
name = self.gen_argument_name(option.name(), is_short_name)
|
||||
else:
|
||||
name = option.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):
|
||||
if self.force_no:
|
||||
if is_short_name:
|
||||
prefix = 'n'
|
||||
else:
|
||||
prefix = 'no-'
|
||||
if '.' in name:
|
||||
sname = name.rsplit('.', 1)
|
||||
name = sname[0] + '.' + prefix + sname[1]
|
||||
else:
|
||||
name = prefix + name
|
||||
if self.force_del:
|
||||
if is_short_name:
|
||||
prefix = 'p'
|
||||
else:
|
||||
prefix = 'pop-'
|
||||
if '.' in name:
|
||||
sname = name.rsplit('.', 1)
|
||||
name = sname[0] + '.' + prefix + sname[1]
|
||||
else:
|
||||
name = prefix + name
|
||||
return name
|
||||
|
||||
def get(self) -> Tuple[Dict]:
|
||||
return self.args, self.kwargs
|
||||
|
||||
|
||||
class TiramisuCmdlineParser(ArgumentParser):
|
||||
def __init__(self,
|
||||
config: Union[Config, ConfigJson],
|
||||
*args,
|
||||
root: str=None,
|
||||
fullpath: bool=True,
|
||||
remove_empty_od: bool=False,
|
||||
display_modified_value: bool=True,
|
||||
formatter_class=HelpFormatter,
|
||||
unrestraint: bool=False,
|
||||
_forhelp: bool=False,
|
||||
**kwargs):
|
||||
if not _forhelp:
|
||||
unrestraint = True
|
||||
self.fullpath = fullpath
|
||||
self.config = config
|
||||
self.root = root
|
||||
self.remove_empty_od = remove_empty_od
|
||||
self.unrestraint = unrestraint
|
||||
self.display_modified_value = display_modified_value
|
||||
if TiramisuHelpFormatter not in formatter_class.__mro__:
|
||||
formatter_class = type('TiramisuHelpFormatter', (TiramisuHelpFormatter, formatter_class), {})
|
||||
formatter_class.remove_empty_od = self.remove_empty_od
|
||||
kwargs['formatter_class'] = formatter_class
|
||||
if not _forhelp and self.unrestraint:
|
||||
subconfig = self.config.unrestraint
|
||||
else:
|
||||
subconfig = self.config
|
||||
if self.root is None:
|
||||
subconfig = subconfig
|
||||
else:
|
||||
subconfig = subconfig.option(self.root)
|
||||
self.namespace = TiramisuNamespace(self.config, self.root)
|
||||
super().__init__(*args, **kwargs)
|
||||
self.register('action', 'help', _TiramisuHelpAction)
|
||||
self._config_to_argparser(_forhelp,
|
||||
subconfig,
|
||||
self.root)
|
||||
|
||||
def _pop_action_class(self, kwargs, default=None):
|
||||
ret = super()._pop_action_class(kwargs, default)
|
||||
if kwargs.get('action') != 'help' and kwargs.get('dest') != 'help':
|
||||
return ret
|
||||
return _TiramisuHelpAction
|
||||
|
||||
def _match_arguments_partial(self,
|
||||
actions,
|
||||
arg_string_pattern):
|
||||
# used only when check first proposal for first value
|
||||
# we have to remove all actions with propertieserror
|
||||
# so only first settable option will be returned
|
||||
actions_pop = []
|
||||
for idx, action in enumerate(actions):
|
||||
if self.config.option(action.dest).property.get(only_raises=True):
|
||||
actions_pop.append(idx)
|
||||
else:
|
||||
break
|
||||
for idx in actions_pop:
|
||||
actions.pop(0)
|
||||
return super()._match_arguments_partial(actions, arg_string_pattern)
|
||||
|
||||
def _is_short_name(self, name, longargument):
|
||||
return len(name) == 1 and not longargument
|
||||
|
||||
def _gen_argument(self, name, is_short_name):
|
||||
if is_short_name:
|
||||
return self.prefix_chars + name
|
||||
return self.prefix_chars * 2 + name
|
||||
|
||||
def _parse_known_args(self, args=None, namespace=None):
|
||||
try:
|
||||
namespace_, args_ = super()._parse_known_args(args, namespace)
|
||||
except (ValueError, LeadershipError, AttributeError) as err:
|
||||
self.error(err)
|
||||
if args != args_ and args_ and args_[0].startswith(self.prefix_chars):
|
||||
# option that was disabled are no more disable
|
||||
# so create a new parser
|
||||
new_parser = TiramisuCmdlineParser(self.config,
|
||||
self.prog,
|
||||
root=self.root,
|
||||
remove_empty_od=self.remove_empty_od,
|
||||
display_modified_value=self.display_modified_value,
|
||||
formatter_class=self.formatter_class,
|
||||
epilog=self.epilog,
|
||||
description=self.description,
|
||||
unrestraint=self.unrestraint,
|
||||
fullpath=self.fullpath)
|
||||
namespace_, args_ = new_parser._parse_known_args(args_, new_parser.namespace)
|
||||
else:
|
||||
if self._registries['action']['help'].needs:
|
||||
# display help only when all variables assignemnt are done
|
||||
self._registries['action']['help'].needs = False
|
||||
helper = self._registries['action']['help'](None)
|
||||
helper.display(self)
|
||||
return namespace_, args_
|
||||
|
||||
def add_argument(self, *args, **kwargs):
|
||||
if args == ('-h', '--help'):
|
||||
super().add_argument(*args, **kwargs)
|
||||
else:
|
||||
raise NotImplementedError(_('do not use add_argument'))
|
||||
|
||||
def add_arguments(self, *args, **kwargs):
|
||||
raise NotImplementedError(_('do not use add_argument'))
|
||||
|
||||
def add_subparsers(self, *args, **kwargs):
|
||||
raise NotImplementedError(_('do not use add_subparsers'))
|
||||
|
||||
def _option_is_not_default(self,
|
||||
properties,
|
||||
type,
|
||||
name,
|
||||
value):
|
||||
if 'positional' not in properties:
|
||||
is_short_name = self._is_short_name(name, 'longargument' in properties)
|
||||
self.prog += ' {}'.format(self._gen_argument(name, is_short_name))
|
||||
if type != 'boolean':
|
||||
if isinstance(value, list):
|
||||
for val in value:
|
||||
self.prog += ' "{}"'.format(val)
|
||||
else:
|
||||
self.prog += ' "{}"'.format(value)
|
||||
|
||||
def _config_list(self,
|
||||
config: Config,
|
||||
prefix: Optional[str],
|
||||
_forhelp: bool,
|
||||
group, level):
|
||||
for obj in config:
|
||||
# do not display frozen option
|
||||
if 'frozen' in obj.property.get():
|
||||
continue
|
||||
if obj.isoptiondescription():
|
||||
if _forhelp:
|
||||
description = obj.description()
|
||||
if description == obj.name():
|
||||
description = None
|
||||
newgroup = self.add_argument_group(obj.path(), description)
|
||||
else:
|
||||
newgroup = group
|
||||
if prefix:
|
||||
prefix_ = prefix + '.' + obj.name()
|
||||
else:
|
||||
prefix_ = obj.path()
|
||||
self._config_to_argparser(_forhelp, obj, prefix_, newgroup, level + 1)
|
||||
elif obj.type() == 'boolean' and not obj.issymlinkoption():
|
||||
if not obj.isleader():
|
||||
yield obj, False, None
|
||||
yield obj, True, None
|
||||
else:
|
||||
yield obj, False, False
|
||||
yield obj, False, True
|
||||
yield obj, True, None
|
||||
elif obj.isleader():
|
||||
yield obj, None, False
|
||||
yield obj, None, True
|
||||
else:
|
||||
yield obj, None, None
|
||||
|
||||
def _config_to_argparser(self,
|
||||
_forhelp: bool,
|
||||
config,
|
||||
prefix: Optional[str],
|
||||
group=None,
|
||||
level=0) -> None:
|
||||
if group is None:
|
||||
group = super()
|
||||
actions = {}
|
||||
leadership_len = None
|
||||
options_is_not_default = {}
|
||||
for option, force_no, force_del in self._config_list(config, prefix, _forhelp, group, level):
|
||||
name = option.name()
|
||||
if name.startswith(self.prefix_chars):
|
||||
raise ValueError(_('name cannot startswith "{}"').format(self.prefix_chars))
|
||||
if option.issymlinkoption():
|
||||
symlink_name = option.option().name()
|
||||
if symlink_name in options_is_not_default:
|
||||
options_is_not_default[symlink_name]['name'] = name
|
||||
if symlink_name in actions:
|
||||
for action in actions[symlink_name]:
|
||||
action.add_argument(option)
|
||||
continue
|
||||
if force_del:
|
||||
value = None
|
||||
elif option.isleader():
|
||||
value = option.value.get()
|
||||
leadership_len = len(value)
|
||||
elif option.isfollower():
|
||||
value = []
|
||||
try:
|
||||
for index in range(leadership_len):
|
||||
value.append(self.config.option(option.path(), index).value.get())
|
||||
except:
|
||||
value = None
|
||||
else:
|
||||
value = option.value.get()
|
||||
if self.fullpath and prefix:
|
||||
name = prefix + '.' + name
|
||||
properties = option.property.get()
|
||||
not_display = not option.isfollower() and not option.owner.isdefault() and value is not None
|
||||
kwargs = _BuildKwargs(name, option, self, properties, force_no, force_del, self.display_modified_value, not_display)
|
||||
if _forhelp and not_display and ((value is not False and not force_no) or (value is False and force_no)):
|
||||
options_is_not_default[option.name()] = {'properties': properties,
|
||||
'type': option.type(),
|
||||
'name': name,
|
||||
'value': value}
|
||||
if not self.display_modified_value:
|
||||
continue
|
||||
if 'positional' in properties:
|
||||
if option.type() == 'boolean':
|
||||
raise ValueError(_('boolean option must not be positional'))
|
||||
if not 'mandatory' in properties:
|
||||
raise ValueError('"positional" argument must be "mandatory" too')
|
||||
if _forhelp:
|
||||
kwargs['default'] = option.value.default()
|
||||
else:
|
||||
kwargs['default'] = value
|
||||
kwargs['nargs'] = '?'
|
||||
else:
|
||||
kwargs['default'] = SUPPRESS
|
||||
if _forhelp and 'mandatory' in properties:
|
||||
kwargs['required'] = True
|
||||
if not force_del and option.type() == 'boolean':
|
||||
if not option.isfollower():
|
||||
if 'storefalse' in properties:
|
||||
if force_no:
|
||||
action = 'store_true'
|
||||
else:
|
||||
action = 'store_false'
|
||||
elif force_no:
|
||||
action = 'store_false'
|
||||
else:
|
||||
action = 'store_true'
|
||||
kwargs['action'] = action
|
||||
else:
|
||||
kwargs['metavar'] = 'INDEX'
|
||||
if option.type() != 'boolean' or force_del:
|
||||
if not force_del:
|
||||
if _forhelp:
|
||||
value = option.value.default()
|
||||
if value not in [None, []]:
|
||||
#kwargs['default'] = kwargs['const'] = option.default()
|
||||
#kwargs['action'] = 'store_const'
|
||||
kwargs['nargs'] = '?'
|
||||
|
||||
if not option.isfollower() and option.ismulti():
|
||||
if _forhelp and 'mandatory' in properties:
|
||||
kwargs['nargs'] = '+'
|
||||
else:
|
||||
kwargs['nargs'] = '*'
|
||||
if option.isfollower() and not option.type() == 'boolean':
|
||||
metavar = option.name().upper()
|
||||
if option.issubmulti():
|
||||
kwargs['nargs'] = '+'
|
||||
else:
|
||||
kwargs['nargs'] = 2
|
||||
if _forhelp and 'mandatory' not in properties:
|
||||
metavar = '[{}]'.format(metavar)
|
||||
if option.type() == 'choice':
|
||||
# do not manage choice with argparse there is problem with integer problem
|
||||
kwargs['metavar'] = ('INDEX', get_choice_list(option, properties, True))
|
||||
else:
|
||||
kwargs['metavar'] = ('INDEX', metavar)
|
||||
if force_del:
|
||||
kwargs['metavar'] = 'INDEX'
|
||||
kwargs['type'] = int
|
||||
elif option.type() == 'string':
|
||||
pass
|
||||
elif option.type() == 'integer' or option.type() == 'boolean':
|
||||
# when boolean we are here only if follower
|
||||
kwargs['type'] = int
|
||||
if _forhelp and option.type() == 'boolean':
|
||||
kwargs['metavar'] = 'INDEX'
|
||||
kwargs['nargs'] = 1
|
||||
elif option.type() == 'choice' and not option.isfollower():
|
||||
# do not manage choice with argparse there is problem with integer problem
|
||||
kwargs['choices'] = get_choice_list(option, properties, False)
|
||||
elif option.type() == 'float':
|
||||
kwargs['type'] = float
|
||||
else:
|
||||
pass
|
||||
actions.setdefault(option.name(), []).append(kwargs)
|
||||
for option_is_not_default in options_is_not_default.values():
|
||||
self._option_is_not_default(**option_is_not_default)
|
||||
for values in actions.values():
|
||||
for value in values:
|
||||
args, kwargs = value.get()
|
||||
group.add_argument(*args, **kwargs)
|
||||
def _valid_mandatory(self):
|
||||
pass
|
||||
|
||||
def parse_args(self,
|
||||
*args,
|
||||
valid_mandatory=True,
|
||||
**kwargs):
|
||||
kwargs['namespace'] = self.namespace
|
||||
try:
|
||||
namespaces = super().parse_args(*args, **kwargs)
|
||||
except PropertiesOptionError as err:
|
||||
name = err._option_bag.option.impl_getname()
|
||||
properties = self.config.option(name).property.get()
|
||||
if self.fullpath and 'positional' not in properties:
|
||||
if len(name) == 1 and 'longargument' not in properties:
|
||||
name = self.prefix_chars + name
|
||||
else:
|
||||
name = self.prefix_chars * 2 + name
|
||||
if err.proptype == ['mandatory']:
|
||||
self.error('the following arguments are required: {}'.format(name))
|
||||
else:
|
||||
self.error('unrecognized arguments: {}'.format(name))
|
||||
if valid_mandatory:
|
||||
errors = []
|
||||
for option in self.config.value.mandatory():
|
||||
properties = option.property.get()
|
||||
if not option.isfollower():
|
||||
if 'positional' not in properties:
|
||||
if self.fullpath:
|
||||
name = option.path()
|
||||
else:
|
||||
name = option.name()
|
||||
is_short_name = self._is_short_name(name, 'longargument' in option.property.get())
|
||||
args = self._gen_argument(name, is_short_name)
|
||||
else:
|
||||
args = option.path()
|
||||
else:
|
||||
if 'positional' not in properties:
|
||||
args = self._gen_argument(option.path(), False)
|
||||
else:
|
||||
args = option.path()
|
||||
if not self.fullpath and '.' in args:
|
||||
args = args.rsplit('.', 1)[1]
|
||||
if 'positional' not in properties:
|
||||
args = self._gen_argument(args, False)
|
||||
errors.append(args)
|
||||
if errors:
|
||||
self.error('the following arguments are required: {}'.format(', '.join(errors)))
|
||||
return namespaces
|
||||
|
||||
def format_usage(self,
|
||||
*args,
|
||||
**kwargs):
|
||||
help_formatter = TiramisuCmdlineParser(self.config,
|
||||
self.prog,
|
||||
root=self.root,
|
||||
fullpath=self.fullpath,
|
||||
remove_empty_od=self.remove_empty_od,
|
||||
display_modified_value=self.display_modified_value,
|
||||
formatter_class=self.formatter_class,
|
||||
epilog=self.epilog,
|
||||
description=self.description,
|
||||
_forhelp=True)
|
||||
return super(TiramisuCmdlineParser, help_formatter).format_usage(*args, **kwargs)
|
||||
|
||||
def format_help(self):
|
||||
help_formatter = TiramisuCmdlineParser(self.config,
|
||||
self.prog,
|
||||
root=self.root,
|
||||
fullpath=self.fullpath,
|
||||
remove_empty_od=self.remove_empty_od,
|
||||
display_modified_value=self.display_modified_value,
|
||||
formatter_class=self.formatter_class,
|
||||
epilog=self.epilog,
|
||||
description=self.description,
|
||||
_forhelp=True)
|
||||
return super(TiramisuCmdlineParser, help_formatter).format_help()
|
||||
|
||||
def get_config(self):
|
||||
return self.config
|
||||
281
tiramisu_cmdline_parser/tiramisu_cmdline_parser.py
Normal file
281
tiramisu_cmdline_parser/tiramisu_cmdline_parser.py
Normal file
|
|
@ -0,0 +1,281 @@
|
|||
# Copyright (C) 2018 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
|
||||
# Free Software Foundation, either version 3 of the License, or (at your
|
||||
# option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||
# details.
|
||||
#
|
||||
# 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/>.
|
||||
|
||||
|
||||
from typing import Union, List, Optional
|
||||
from argparse import ArgumentParser, Namespace, SUPPRESS, _HelpAction
|
||||
try:
|
||||
from tiramisu import Config
|
||||
from tiramisu.error import PropertiesOptionError
|
||||
except ImportError:
|
||||
Config = None
|
||||
from tiramisu_json_api.error import PropertiesOptionError
|
||||
try:
|
||||
from tiramisu_json_api import Config as ConfigJson
|
||||
if Config is None:
|
||||
Config = ConfigJson
|
||||
except ImportError:
|
||||
ConfigJson = Config
|
||||
|
||||
|
||||
class TiramisuNamespace(Namespace):
|
||||
def _populate(self):
|
||||
#self._config.property.read_only()
|
||||
for tiramisu_key, tiramisu_value in self._config.value.dict().items():
|
||||
option = self._config.option(tiramisu_key)
|
||||
if not option.option.issymlinkoption():
|
||||
if tiramisu_value == [] and option.option.ismulti() and option.owner.isdefault():
|
||||
tiramisu_value = None
|
||||
super().__setattr__(tiramisu_key, tiramisu_value)
|
||||
#self._config.property.read_write()
|
||||
|
||||
def __init__(self, config):
|
||||
self._config = config
|
||||
super().__init__()
|
||||
|
||||
def __setattr__(self, key, value):
|
||||
if key == '_config':
|
||||
super().__setattr__(key, value)
|
||||
return
|
||||
# self._config.property.read_write()
|
||||
option = self._config.option(key)
|
||||
if option.option.ismulti() and value is not None and not isinstance(value, list):
|
||||
value = [value]
|
||||
option.value.set(value)
|
||||
|
||||
def __getattribute__(self, key):
|
||||
if key == '__dict__' and hasattr(self, '_config'):
|
||||
self._populate()
|
||||
return super().__getattribute__(key)
|
||||
|
||||
|
||||
class _TiramisuHelpAction(_HelpAction):
|
||||
needs = False
|
||||
def __call__(self, *args, **kwargs):
|
||||
_TiramisuHelpAction.needs = True
|
||||
|
||||
def display(self, parser):
|
||||
_HelpAction.__call__(self, parser, None, None)
|
||||
|
||||
|
||||
class TiramisuCmdlineParser(ArgumentParser):
|
||||
def __init__(self,
|
||||
config: Union[Config, ConfigJson],
|
||||
*args,
|
||||
fullpath: bool=True,
|
||||
_forhelp: bool=False,
|
||||
**kwargs):
|
||||
self.fullpath = fullpath
|
||||
self.config = config
|
||||
super().__init__(*args, **kwargs)
|
||||
self.register('action', 'help', _TiramisuHelpAction)
|
||||
self._config_to_argparser(_forhelp,
|
||||
self.config.option)
|
||||
|
||||
def _pop_action_class(self, kwargs, default=None):
|
||||
ret = super()._pop_action_class(kwargs, default)
|
||||
if kwargs.get('action') != 'help' and kwargs.get('dest') != 'help':
|
||||
return ret
|
||||
return _TiramisuHelpAction
|
||||
|
||||
def _match_arguments_partial(self,
|
||||
actions,
|
||||
arg_string_pattern):
|
||||
# used only when check first proposal for first value
|
||||
# we have to remove all actions with propertieserror
|
||||
# so only first settable option will be returned
|
||||
actions_pop = []
|
||||
for idx, action in enumerate(actions):
|
||||
if self.config.option(action.dest).property.get(only_raises=True):
|
||||
actions_pop.append(idx)
|
||||
else:
|
||||
break
|
||||
for idx in actions_pop:
|
||||
actions.pop(0)
|
||||
return super()._match_arguments_partial(actions, arg_string_pattern)
|
||||
|
||||
def _parse_known_args(self, args=None, namespace=None):
|
||||
|
||||
namespace_, args_ = super()._parse_known_args(args, namespace)
|
||||
if args != args_ and args_ and args_[0].startswith(self.prefix_chars):
|
||||
# option that was disabled are no more disable
|
||||
# so create a new parser
|
||||
new_parser = TiramisuCmdlineParser(self.config,
|
||||
self.prog,
|
||||
fullpath=self.fullpath)
|
||||
namespace_, args_ = new_parser._parse_known_args(args_, namespace)
|
||||
else:
|
||||
if self._registries['action']['help'].needs:
|
||||
# display help only when all variables assignemnt are done
|
||||
self._registries['action']['help'].needs = False
|
||||
helper = self._registries['action']['help'](None)
|
||||
helper.display(self)
|
||||
return namespace_, args_
|
||||
|
||||
def add_argument(self, *args, **kwargs):
|
||||
if args == ('-h', '--help'):
|
||||
super().add_argument(*args, **kwargs)
|
||||
else:
|
||||
raise NotImplementedError('do not use add_argument')
|
||||
|
||||
def add_arguments(self, *args, **kwargs):
|
||||
raise NotImplementedError('do not use add_argument')
|
||||
|
||||
def add_subparsers(self, *args, **kwargs):
|
||||
raise NotImplementedError('do not use add_subparsers')
|
||||
|
||||
def _gen_argument(self, name, properties):
|
||||
if len(name) == 1 and 'longargument' not in properties:
|
||||
return self.prefix_chars + name
|
||||
return self.prefix_chars * 2 + name
|
||||
|
||||
def _config_to_argparser(self,
|
||||
_forhelp: bool,
|
||||
config,
|
||||
prefix: Optional[str]=None,
|
||||
group=None) -> None:
|
||||
if group is None:
|
||||
group = super()
|
||||
actions = {}
|
||||
for obj in config.list(type='all'):
|
||||
option = obj.option
|
||||
if option.isoptiondescription():
|
||||
if _forhelp:
|
||||
group = self.add_argument_group(option.doc())
|
||||
if prefix:
|
||||
prefix_ = prefix + '.' + option.name()
|
||||
else:
|
||||
prefix_ = option.path()
|
||||
self._config_to_argparser(_forhelp, obj, prefix_, group)
|
||||
continue
|
||||
if 'frozen' in option.properties():
|
||||
continue
|
||||
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
|
||||
properties = obj.property.get()
|
||||
kwargs = {'help': option.doc().replace('%', '%%')}
|
||||
if option.issymlinkoption():
|
||||
actions[option.name(follow_symlink=True)][0].insert(0, self._gen_argument(name, properties))
|
||||
continue
|
||||
if 'positional' in properties:
|
||||
if not 'mandatory' in properties:
|
||||
raise ValueError('"positional" argument must be "mandatory" too')
|
||||
args = [option.path()]
|
||||
if _forhelp:
|
||||
kwargs['default'] = obj.value.default()
|
||||
else:
|
||||
kwargs['default'] = obj.value.get()
|
||||
kwargs['nargs'] = '?'
|
||||
else:
|
||||
kwargs['dest'] = option.path()
|
||||
kwargs['default'] = SUPPRESS
|
||||
args = [self._gen_argument(name, properties)]
|
||||
if _forhelp and 'mandatory' in properties:
|
||||
kwargs['required'] = True
|
||||
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:
|
||||
action = 'store_true'
|
||||
else:
|
||||
action = 'store_false'
|
||||
kwargs['action'] = action
|
||||
else:
|
||||
if _forhelp:
|
||||
value = obj.value.default()
|
||||
else:
|
||||
value = obj.value.get()
|
||||
if value not in [None, []]:
|
||||
#kwargs['default'] = kwargs['const'] = option.default()
|
||||
#kwargs['action'] = 'store_const'
|
||||
kwargs['nargs'] = '?'
|
||||
if option.ismulti():
|
||||
if _forhelp and 'mandatory' in properties:
|
||||
kwargs['nargs'] = '+'
|
||||
else:
|
||||
kwargs['nargs'] = '*'
|
||||
if option.type() == 'string':
|
||||
pass
|
||||
elif option.type() == 'integer':
|
||||
kwargs['type'] = int
|
||||
elif option.type() == 'choice':
|
||||
kwargs['choices'] = obj.value.list()
|
||||
else:
|
||||
pass
|
||||
#raise NotImplementedError('not supported yet')
|
||||
actions[option.name()] = (args, kwargs)
|
||||
for args, kwargs in actions.values():
|
||||
group.add_argument(*args, **kwargs)
|
||||
|
||||
|
||||
def parse_args(self,
|
||||
*args,
|
||||
valid_mandatory=True,
|
||||
**kwargs):
|
||||
kwargs['namespace'] = TiramisuNamespace(self.config)
|
||||
try:
|
||||
namespaces = super().parse_args(*args, **kwargs)
|
||||
del namespaces.__dict__['_config']
|
||||
except PropertiesOptionError as err:
|
||||
name = err._option_bag.option.impl_getname()
|
||||
properties = self.config.option(name).property.get()
|
||||
if 'positional' not in properties:
|
||||
if len(name) == 1 and 'longargument' not in properties:
|
||||
name = self.prefix_chars + name
|
||||
else:
|
||||
name = self.prefix_chars * 2 + name
|
||||
if err.proptype == ['mandatory']:
|
||||
self.error('the following arguments are required: {}'.format(name))
|
||||
else:
|
||||
self.error('unrecognized arguments: {}'.format(name))
|
||||
if valid_mandatory:
|
||||
for key in self.config.value.mandatory():
|
||||
properties = self.config.option(key).property.get()
|
||||
if 'positional' not in properties:
|
||||
if self.fullpath or '.' not in key:
|
||||
name = key
|
||||
else:
|
||||
name = key.rsplit('.', 1)[1]
|
||||
args = self._gen_argument(name, self.config.option(key).property.get())
|
||||
else:
|
||||
args = key
|
||||
self.error('the following arguments are required: {}'.format(args))
|
||||
return namespaces
|
||||
|
||||
def format_usage(self,
|
||||
*args,
|
||||
**kwargs):
|
||||
help_formatter = TiramisuCmdlineParser(self.config,
|
||||
self.prog,
|
||||
fullpath=self.fullpath,
|
||||
_forhelp=True)
|
||||
return super(TiramisuCmdlineParser, help_formatter).format_usage(*args, **kwargs)
|
||||
|
||||
def format_help(self,
|
||||
*args,
|
||||
**kwargs):
|
||||
help_formatter = TiramisuCmdlineParser(self.config,
|
||||
self.prog,
|
||||
fullpath=self.fullpath,
|
||||
_forhelp=True)
|
||||
return super(TiramisuCmdlineParser, help_formatter).format_help(*args, **kwargs)
|
||||
|
||||
def get_config(self):
|
||||
return self.config
|
||||
Loading…
Reference in a new issue