update help() in api

This commit is contained in:
Emmanuel Garette 2018-04-07 20:15:19 +02:00
parent b2cc5f7913
commit c3be5e82ba
9 changed files with 281 additions and 164 deletions

View File

@ -17,7 +17,7 @@ ICON = u'\u2937'
OPTIONS_TYPE = {'str': {'type': str, OPTIONS_TYPE = {'str': {'type': str,
'option': StrOption} 'option': StrOption}
} }
PROPERTIES = ['hidden', 'disabled'] PROPERTIES = ['hidden', 'disabled', 'mandatory']
PROPERTIES_LIST = ['prop1', 'prop2'] PROPERTIES_LIST = ['prop1', 'prop2']
OWNER = 'user' OWNER = 'user'
@ -1068,7 +1068,7 @@ def autocheck_option_get(api, pathread, pathwrite, confread, confwrite, **kwargs
name = pathread.rsplit('.', 1)[1] name = pathread.rsplit('.', 1)[1]
else: else:
name = pathread name = pathread
assert api.option.get(pathread).impl_getname() == name assert api.unrestraint.option(pathread).option.name() == name
@autocheck @autocheck
@ -1088,28 +1088,28 @@ def autocheck_find(api, pathread, pathwrite, confread, confwrite, **kwargs):
name = pathread.rsplit('.', 1)[1] name = pathread.rsplit('.', 1)[1]
else: else:
name = pathread name = pathread
option = _getoption(api.option.get(pathread)) option = _getoption(api.unrestraint.option(pathread).option.get())
def do(conf): def do(conf):
if not kwargs.get('permissive', False) and not kwargs.get('propertyerror', False): if not kwargs.get('permissive', False) and not kwargs.get('propertyerror', False):
assert option == _getoption(api.config(conf).option.find_first(name)) assert option == _getoption(api.config(conf).option.find(name, first=True))
assert option == _getoption(api.forcepermissive.config(conf).option.find_first(name)) assert option == _getoption(api.forcepermissive.config(conf).option.find(name, first=True))
elif kwargs.get('permissive', False): elif kwargs.get('permissive', False):
raises(AttributeError, "api.config(conf).option.find_first(name)") raises(AttributeError, "api.config(conf).option.find(name, first=True)")
assert option == _getoption(api.forcepermissive.config(conf).option.find_first(name)) assert option == _getoption(api.forcepermissive.config(conf).option.find(name, first=True))
else: else:
raises(AttributeError, "api.config(conf).option.find_first(name)") raises(AttributeError, "api.config(conf).option.find(name, first=True)")
raises(AttributeError, "api.forcepermissive.config(conf).option.find_first(name)") raises(AttributeError, "api.forcepermissive.config(conf).option.find(name, first=True)")
assert option == _getoption(api.unrestraint.config(conf).option.find_first(name)) assert option == _getoption(api.unrestraint.config(conf).option.find(name, first=True))
assert [option] == _getoptions(api.unrestraint.config(conf).option.find(name)) assert [option] == _getoptions(api.unrestraint.config(conf).option.find(name))
assert pathread == api.unrestraint.config(conf).option.find_first(name, 'path') assert pathread == api.unrestraint.config(conf).option.find(name, 'path', first=True)
assert [pathread] == api.unrestraint.config(conf).option.find(name, 'path') assert [pathread] == api.unrestraint.config(conf).option.find(name, 'path')
do(confread) do(confread)
if confread != confwrite: if confread != confwrite:
do(confwrite) do(confwrite)
def check_all(cfg, paths, path, meta, multi, default, default_multi, require, consistency, callback, symlink, weakrefs, **kwargs): def check_all(cfg, paths_, path, meta, multi, default, default_multi, require, consistency, callback, symlink, weakrefs, **kwargs):
def _build_make_dict(): def _build_make_dict():
dico = {} dico = {}
dico_value = {} dico_value = {}
@ -1132,7 +1132,7 @@ def check_all(cfg, paths, path, meta, multi, default, default_multi, require, co
is_master = False is_master = False
dyns = [] dyns = []
has_value = False has_value = False
for cpath, options in paths.items(): for cpath, options in paths_.items():
if options is None: if options is None:
break break
if '.' in cpath: if '.' in cpath:
@ -1172,7 +1172,7 @@ def check_all(cfg, paths, path, meta, multi, default, default_multi, require, co
kwargs['default'] = None kwargs['default'] = None
if is_dyn and dyns: if is_dyn and dyns:
idx = 0 idx = 0
for cpath in list(paths.keys())[len(dyns):]: for cpath in list(paths_.keys())[len(dyns):]:
if dyns[idx]: if dyns[idx]:
dico[cpath] = default_value dico[cpath] = default_value
if symlink: if symlink:
@ -1227,7 +1227,7 @@ def check_all(cfg, paths, path, meta, multi, default, default_multi, require, co
dico[cpath + 'extraoptconsistency'] = value dico[cpath + 'extraoptconsistency'] = value
dico_value[cpath + 'extraoptconsistency'] = value dico_value[cpath + 'extraoptconsistency'] = value
if is_master: if is_master:
for cpath in list(paths.keys())[len(dyns):]: for cpath in list(paths_.keys())[len(dyns):]:
if cpath.endswith('.first') or cpath.endswith('.firstval1') or cpath.endswith('.firstval2'): if cpath.endswith('.first') or cpath.endswith('.firstval1') or cpath.endswith('.firstval2'):
second_path = cpath.rsplit('.', 1)[0] + '.second' second_path = cpath.rsplit('.', 1)[0] + '.second'
third_path = cpath.rsplit('.', 1)[0] + '.third' third_path = cpath.rsplit('.', 1)[0] + '.third'
@ -1698,6 +1698,8 @@ def paths(request):
def test_options(paths): def test_options(paths):
def get_kwargs_option(options, kwargs, od=False): def get_kwargs_option(options, kwargs, od=False):
if options.get('mandatory', False):
kwargs['mandatory'] = True
if options.get('hidden', False) is True: if options.get('hidden', False) is True:
kwargs['permissive'] = True kwargs['permissive'] = True
if not od: if not od:

View File

@ -163,8 +163,8 @@ def test_config_impl_get_path_by_opt():
descr = make_description() descr = make_description()
config = Config(descr) config = Config(descr)
api = getapi(config) api = getapi(config)
dummy = api.option.get('gc.dummy') dummy = api.option('gc.dummy').option.get()
boo = api.option.get('bool') boo = api.option('bool').option.get()
unknown = IntOption('test', '') unknown = IntOption('test', '')
unknown unknown
assert config.cfgimpl_get_description().impl_get_path_by_opt(boo) == 'bool' assert config.cfgimpl_get_description().impl_get_path_by_opt(boo) == 'bool'

View File

@ -165,17 +165,17 @@ def test_find_in_config():
api.permissive.set(frozenset(['hidden'])) api.permissive.set(frozenset(['hidden']))
ret = api.option.find('dummy') ret = api.option.find('dummy')
assert len(ret) == 1 assert len(ret) == 1
_is_same_opt(ret[0], api.option.get('gc.dummy')) _is_same_opt(ret[0], api.option('gc.dummy').option.get())
# #
ret = api.option.find_first('dummy') ret = api.option.find('dummy', first=True)
_is_same_opt(ret, api.option.get('gc.dummy')) _is_same_opt(ret, api.option('gc.dummy').option.get())
# #
ret = api.option.find('float') ret = api.option.find('float')
assert len(ret) == 2 assert len(ret) == 2
_is_same_opt(ret[0], api.option.get('gc.float')) _is_same_opt(ret[0], api.option('gc.float').option.get())
_is_same_opt(ret[1], api.option.get('float')) _is_same_opt(ret[1], api.option('float').option.get())
# #
_is_same_opt(api.option.find_first('bool'), api.option.get('gc.gc2.bool')) _is_same_opt(api.option.find('bool', first=True), api.option('gc.gc2.bool').option.get())
#_is_same_opt(conf.find_first(byname='bool', byvalue=True), conf.unwrap_from_path('bool')) #_is_same_opt(conf.find_first(byname='bool', byvalue=True), conf.unwrap_from_path('bool'))
#_is_same_opt(conf.find_first(byname='dummy'), conf.unwrap_from_path('gc.dummy')) #_is_same_opt(conf.find_first(byname='dummy'), conf.unwrap_from_path('gc.dummy'))
#_is_same_opt(conf.find_first(byname='float'), conf.unwrap_from_path('gc.float')) #_is_same_opt(conf.find_first(byname='float'), conf.unwrap_from_path('gc.float'))
@ -385,3 +385,12 @@ def test_invalid_option():
raises(ValueError, "BroadcastOption('a', '', multi=True, default_multi='string')") raises(ValueError, "BroadcastOption('a', '', multi=True, default_multi='string')")
raises(ValueError, "DomainnameOption('a', '', multi=True, default_multi='string')") raises(ValueError, "DomainnameOption('a', '', multi=True, default_multi='string')")
raises(ValueError, "DomainnameOption('a', '', multi=True, default_multi=1)") raises(ValueError, "DomainnameOption('a', '', multi=True, default_multi=1)")
def test_help():
stro = StrOption('s', '', multi=True)
od1 = OptionDescription('o', '', [stro])
od2 = OptionDescription('o', '', [od1])
cfg = Config(od2)
api = getapi(cfg)
api.help(_display=False, _valid=True)

View File

@ -639,8 +639,8 @@ def test_find_dyndescription_context():
od2 = OptionDescription('od', '', [od]) od2 = OptionDescription('od', '', [od])
api = getapi(Config(od2)) api = getapi(Config(od2))
api.option('od.dodval1.stval1').value.set('yes') api.option('od.dodval1.stval1').value.set('yes')
assert api.option.find_first('stval1', type='value') == "yes" assert api.option.find('stval1', type='value', first=True) == "yes"
assert isinstance(api.option.find_first('stval1', type='option'), DynSymLinkOption) assert isinstance(api.option.find('stval1', type='option', first=True), DynSymLinkOption)
#assert api.option.find(bytype=StrOption, type='path') == ['od.dodval1.stval1', 'od.dodval2.stval2', 'od.val1'] #assert api.option.find(bytype=StrOption, type='path') == ['od.dodval1.stval1', 'od.dodval2.stval2', 'od.val1']
#opts = api.option.find(byvalue='yes') #opts = api.option.find(byvalue='yes')
#assert len(opts) == 1 #assert len(opts) == 1

View File

@ -127,7 +127,7 @@ def test_contexts():
def test_find(): def test_find():
api = make_metaconfig() api = make_metaconfig()
assert [1] == api.option.find('i2', type='value') assert [1] == api.option.find('i2', type='value')
assert 1 == api.option.find_first('i2', type='value') assert 1 == api.option.find('i2', type='value', first=True)
assert api.option.make_dict() == {'od1.i4': 2, 'od1.i1': None, 'od1.i3': None, assert api.option.make_dict() == {'od1.i4': 2, 'od1.i1': None, 'od1.i3': None,
'od1.i2': 1, 'od1.i5': [2]} 'od1.i2': 1, 'od1.i5': [2]}
@ -203,15 +203,15 @@ def test_meta_meta_set():
conf1 = meta.getconfig('conf1') conf1 = meta.getconfig('conf1')
conf2 = meta.getconfig('conf2') conf2 = meta.getconfig('conf2')
assert api.config('meta.conf1').option('od1.i1').value.get() == api.config('meta.conf2').option('od1.i1').value.get() == 7 assert api.config('meta.conf1').option('od1.i1').value.get() == api.config('meta.conf2').option('od1.i1').value.get() == 7
assert [conf1, conf2] == api.config.find_first('i1', byvalue=7).cfgimpl_get_children() assert [conf1, conf2] == api.config.find('i1', byvalue=7, first=True).cfgimpl_get_children()
api.config('meta.conf1').option('od1.i1').value.set(8) api.config('meta.conf1').option('od1.i1').value.set(8)
assert [conf1, conf2] == api.config.find_first('i1').cfgimpl_get_children() assert [conf1, conf2] == api.config.find('i1', first=True).cfgimpl_get_children()
assert [conf2] == api.config.find_first('i1', byvalue=7).cfgimpl_get_children() assert [conf2] == api.config.find('i1', byvalue=7, first=True).cfgimpl_get_children()
assert [conf1] == api.config.find_first('i1', byvalue=8).cfgimpl_get_children() assert [conf1] == api.config.find('i1', byvalue=8, first=True).cfgimpl_get_children()
assert [conf1, conf2] == api.config.find_first('i5', byvalue=2).cfgimpl_get_children() assert [conf1, conf2] == api.config.find('i5', byvalue=2, first=True).cfgimpl_get_children()
raises(AttributeError, "api.config.find_first('i1', byvalue=10)") raises(AttributeError, "api.config.find('i1', byvalue=10, first=True)")
raises(AttributeError, "api.config.find_first('not', byvalue=10)") raises(AttributeError, "api.config.find('not', byvalue=10, first=True)")
raises(AttributeError, "api.config.find_first('i6')") raises(AttributeError, "api.config.find('i6', first=True)")
raises(ValueError, "api.value.set('od1.i6', 7, only_config=True, force_default=True)") raises(ValueError, "api.value.set('od1.i6', 7, only_config=True, force_default=True)")
raises(ValueError, "api.value.set('od1.i6', 7, only_config=True, force_default_if_same=True)") raises(ValueError, "api.value.set('od1.i6', 7, only_config=True, force_default_if_same=True)")
raises(ValueError, "api.value.set('od1.i6', 7, only_config=True, force_dont_change_value=True)") raises(ValueError, "api.value.set('od1.i6', 7, only_config=True, force_dont_change_value=True)")
@ -246,7 +246,7 @@ def test_group_find_firsts():
conf2 = Config(od2, session_id='conf2') conf2 = Config(od2, session_id='conf2')
grp = GroupConfig([conf1, conf2]) grp = GroupConfig([conf1, conf2])
api = getapi(grp) api = getapi(grp)
assert [conf1, conf2] == api.config.find_first('i1').cfgimpl_get_children() assert [conf1, conf2] == api.config.find('i1', first=True).cfgimpl_get_children()
def test_group_group(): def test_group_group():
@ -295,13 +295,13 @@ def test_meta_master_slaves():
conf2 = Config(od, session_id='conf2') conf2 = Config(od, session_id='conf2')
api = getapi(MetaConfig([conf1, conf2])) api = getapi(MetaConfig([conf1, conf2]))
api.property.read_only() api.property.read_only()
assert [conf1, conf2] == api.config.find_first('ip_admin_eth0').cfgimpl_get_children() assert [conf1, conf2] == api.config.find('ip_admin_eth0', first=True).cfgimpl_get_children()
assert [conf1, conf2] == api.config.find_first('netmask_admin_eth0').cfgimpl_get_children() assert [conf1, conf2] == api.config.find('netmask_admin_eth0', first=True).cfgimpl_get_children()
api.property.read_write() api.property.read_write()
raises(AttributeError, "api.config.find_first('netmask_admin_eth0')") raises(AttributeError, "api.config.find('netmask_admin_eth0', first=True)")
assert [conf1, conf2] == api.unrestraint.config.find_first('netmask_admin_eth0').cfgimpl_get_children() assert [conf1, conf2] == api.unrestraint.config.find('netmask_admin_eth0', first=True).cfgimpl_get_children()
api.property.read_only() api.property.read_only()
assert [conf1, conf2] == api.config.find_first('netmask_admin_eth0').cfgimpl_get_children() assert [conf1, conf2] == api.config.find('netmask_admin_eth0', first=True).cfgimpl_get_children()
def test_meta_master_slaves_value2(): def test_meta_master_slaves_value2():

View File

@ -384,8 +384,8 @@ def test_access_by_get():
descr = make_description() descr = make_description()
api = getapi(Config(descr)) api = getapi(Config(descr))
raises(AttributeError, "api.option.find('idontexist')") raises(AttributeError, "api.option.find('idontexist')")
assert api.option.find_first('wantref', type='value') is False assert api.option.find('wantref', type='value', first=True) is False
assert api.option.find_first('dummy', type='value') is False assert api.option.find('dummy', type='value', first=True) is False
def test_access_by_get_whith_hide(): def test_access_by_get_whith_hide():

View File

@ -52,7 +52,7 @@ def test_base_config():
api.property.read_write() api.property.read_write()
assert api.option('creole.general.activer_proxy_client').value.get() is False assert api.option('creole.general.activer_proxy_client').value.get() is False
assert api.option('creole.general.nom_machine').value.get() == "eoleng" assert api.option('creole.general.nom_machine').value.get() == "eoleng"
assert api.option.find_first('nom_machine', type='value') == "eoleng" assert api.option.find('nom_machine', type='value', first=True) == "eoleng"
result = {'general.numero_etab': None, 'general.nombre_interfaces': 1, result = {'general.numero_etab': None, 'general.nombre_interfaces': 1,
'general.serveur_ntp': [], 'interface1.ip_admin_eth0.ip_admin_eth0': None, 'general.serveur_ntp': [], 'interface1.ip_admin_eth0.ip_admin_eth0': None,
'general.mode_conteneur_actif': False, 'general.time_zone': 'Paris', 'general.mode_conteneur_actif': False, 'general.time_zone': 'Paris',

View File

@ -14,7 +14,7 @@
# You should have received a copy of the GNU Lesser General Public License # You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
# ____________________________________________________________ # ____________________________________________________________
from inspect import ismethod, getdoc from inspect import ismethod, getdoc, signature
from .error import APIError, ConfigError, SlaveError from .error import APIError, ConfigError, SlaveError
from .i18n import _ from .i18n import _
from .setting import ConfigBag, owners, undefined, FORBIDDEN_SET_PROPERTIES from .setting import ConfigBag, owners, undefined, FORBIDDEN_SET_PROPERTIES
@ -36,6 +36,9 @@ COUNT_TIME = False
#COUNT_TIME = {} #COUNT_TIME = {}
EXCLUDE_HELP = ('help', '_get_option', '_test_slave_index')
def count(func): def count(func):
global MOD_COUNT_TIME global MOD_COUNT_TIME
class_name = func.__str__().split()[1].split('.')[0] class_name = func.__str__().split()[1].split('.')[0]
@ -80,8 +83,76 @@ def display_count():
MOD_COUNT_TIME = deepcopy(COUNT_TIME) MOD_COUNT_TIME = deepcopy(COUNT_TIME)
class CommonTiramisu(object): class TiramisuHelp:
icon = '\u2937'
tmpl_help = '{0}{1} {2}: \n{0} {3}\n'
def help(self,
init=True,
space="",
root='',
_display=True,
_valid=False):
options = []
if init and isinstance(self, TiramisuAPI):
options.append(self.tmpl_help.format(space, self.icon, root + 'unrestraint', _('access to option without property restriction')))
options.append(self.tmpl_help.format(space, self.icon, root + 'forcepermissive', _('access to option without verifying permissive property')))
root = '[unrestraint.|forcepermissive.]'
modules = list(self.registers.keys())
modules.sort()
for module_name in modules:
module = self.registers[module_name]
instance_module = module(None)
if isinstance(instance_module, TiramisuDispatcher):
if _valid and not getdoc(module.__call__):
raise Exception('unknown doc for {}'.format('__call__'))
module_doc = _(getdoc(module.__call__))
module_signature = signature(module.__call__)
module_args = [str(module_signature.parameters[key]) for key in list(module_signature.parameters.keys())[1:]]
module_args = '(' + ', '.join(module_args) + ')'
options.append(self.tmpl_help.format(space, self.icon, root + module_name + module_args, module_doc))
if hasattr(module, 'subhelp'):
instance_submodule = module.subhelp(None, None, None, None, None)
options.extend(instance_submodule.help(init=False, space=space + ' ', root=root + module_name + module_args + '.'))
else:
root = root + '[config(path).]'
if isinstance(instance_module, CommonTiramisuOption):
if _valid and not getdoc(module):
raise Exception('unknown doc for {}'.format(module.__class__.__name__))
module_doc = _(getdoc(module))
options.append(self.tmpl_help.format(space, self.icon, root + module_name, module_doc))
if isinstance(instance_module, TiramisuContext):
if _valid and not getdoc(module):
raise Exception('unknown doc for {}'.format(module.__class__.__name__))
module_doc = _(getdoc(module))
options.append(self.tmpl_help.format(space, self.icon, root + module_name, module_doc))
options.extend(instance_module.help(init=False, space=space + ' ', root=root + '{}.'.format(module_name)))
funcs = dir(self)
funcs.sort()
for func_name in funcs:
if not func_name.startswith('__') and not func_name in EXCLUDE_HELP:
func = getattr(self, func_name)
if ismethod(func):
module_signature = signature(func)
module_args = list(module_signature.parameters.keys())
module_args = [str(module_signature.parameters[key]) for key in module_signature.parameters.keys()]
module_args = '(' + ', '.join(module_args) + ')'
if func_name.startswith('_'):
func_name = func_name[1:]
if _valid and not getdoc(func):
raise Exception('unknown doc for {}'.format(func.__name__))
options.append(self.tmpl_help.format(space, self.icon, root + func_name + module_args, _(getdoc(func))))
if init:
if _display:
print('\n'.join(options))
else:
return options
class CommonTiramisu(TiramisuHelp):
allow_optiondescription = True allow_optiondescription = True
registers = {}
def _get_option(self): def _get_option(self):
option = self.config_bag.option option = self.config_bag.option
@ -108,27 +179,22 @@ class CommonTiramisu(object):
class CommonTiramisuOption(CommonTiramisu): class CommonTiramisuOption(CommonTiramisu):
icon = '\u2937'
tmpl_help = u' {} {}: {}'
allow_unrestraint = False
allow_optiondescription = False allow_optiondescription = False
slave_need_index = True slave_need_index = True
def __init__(self, def __init__(self,
name, name,
path, path=None,
index, index=None,
subconfig, subconfig=None,
config_bag): config_bag=None):
self.path = path self.path = path
self.index = index self.index = index
self.config_bag = config_bag self.config_bag = config_bag
self._name = name self._name = name
self.subconfig = subconfig self.subconfig = subconfig
if self.slave_need_index: if config_bag is not None and self.slave_need_index:
self._test_slave_index() self._test_slave_index()
if not self.allow_unrestraint and self.config_bag.force_unrestraint:
self._unrestraint_not_allowed(self.config_bag.force_unrestraint)
def _test_slave_index(self): def _test_slave_index(self):
option = self._get_option() option = self._get_option()
@ -138,37 +204,21 @@ class CommonTiramisuOption(CommonTiramisu):
elif self.index is not None and not option.impl_is_master_slaves('slave'): elif self.index is not None and not option.impl_is_master_slaves('slave'):
raise APIError('index must be set only with a slave option') raise APIError('index must be set only with a slave option')
def _unrestraint_not_allowed(self, force_unrestraint):
name = self.__class__.__name__[14:].lower()
raise APIError(_('{} cannot be unrestraint').format(name))
def __getattr__(self, name): def __getattr__(self, name):
if name == 'help': if not hasattr(CommonTiramisuOption, name):
return self._help() raise APIError(_('unknown method {}').format(name))
else: else:
if not hasattr(CommonTiramisuOption, name): super().__getattribute__(name)
raise APIError(_('unknown method {}').format(name))
else:
super().__getattribute__(name)
def _help(self):
txt = []
for func_name in dir(self):
if not func_name.startswith('_'):
func = getattr(self, func_name)
if ismethod(func):
txt.append(self.tmpl_help.format(self.icon, func_name, getdoc(func)))
return '\n'.join(txt)
class TiramisuOptionOption(CommonTiramisuOption): class TiramisuOptionOption(CommonTiramisuOption):
"""get information from an option""" """manage option"""
allow_unrestraint = True
allow_optiondescription = True allow_optiondescription = True
slave_need_index = False slave_need_index = False
@count @count
def get(self): def get(self):
"""get Tiramisu option"""
return self._get_option() return self._get_option()
@count @count
@ -203,41 +253,49 @@ class TiramisuOptionOption(CommonTiramisuOption):
@count @count
def doc(self): def doc(self):
"""get option document"""
option = self._get_option() option = self._get_option()
return option.impl_get_display_name() return option.impl_get_display_name()
@count @count
def name(self): def name(self):
"""get option name"""
self._get_option() self._get_option()
return self._name return self._name
@count @count
def _default(self): def _default(self):
"""get default value for an option (not for optiondescription)"""
option = self._get_option() option = self._get_option()
return option.impl_getdefault() return option.impl_getdefault()
@count @count
def _defaultmulti(self): def _defaultmulti(self):
"""get default value when added a value for a multi option (not for optiondescription)"""
option = self._get_option() option = self._get_option()
return option.impl_getdefault_multi() return option.impl_getdefault_multi()
@count @count
def has_dependency(self, self_is_dep=True): def has_dependency(self, self_is_dep=True):
"""test if option has dependency"""
option = self._get_option() option = self._get_option()
return option.impl_has_dependency(self_is_dep) return option.impl_has_dependency(self_is_dep)
@count @count
def _consistencies(self): def _consistencies(self):
"""get consistencies for an option (not for optiondescription)"""
option = self._get_option() option = self._get_option()
return option.get_consistencies() return option.get_consistencies()
@count @count
def _callbacks(self): def _callbacks(self):
"""get callbacks for an option (not for optiondescription)"""
option = self._get_option() option = self._get_option()
return option.impl_get_callback() return option.impl_get_callback()
@count @count
def requires(self): def requires(self):
"""get requires for an option"""
option = self._get_option() option = self._get_option()
return option.impl_getrequires() return option.impl_getrequires()
@ -251,26 +309,27 @@ class TiramisuOptionOption(CommonTiramisuOption):
raise APIError(_('{} is unknown').format(name)) raise APIError(_('{} is unknown').format(name))
def isoptiondescription(self): def isoptiondescription(self):
"""test if option is an optiondescription"""
return self._get_option().impl_is_optiondescription() return self._get_option().impl_is_optiondescription()
class TiramisuOptionOwner(CommonTiramisuOption): class TiramisuOptionOwner(CommonTiramisuOption):
"""manager option's owner""" """manager option's owner"""
allow_unrestraint = True
def __init__(self, def __init__(self,
name, name,
path, path=None,
index, index=None,
subconfig, subconfig=None,
config_bag): config_bag=None):
super().__init__(name, super().__init__(name,
path, path,
index, index,
subconfig, subconfig,
config_bag) config_bag)
self.values = self.config_bag.config.cfgimpl_get_values() if config_bag:
self.values = self.config_bag.config.cfgimpl_get_values()
@count @count
def get(self): def get(self):
@ -309,24 +368,25 @@ class TiramisuOptionOwner(CommonTiramisuOption):
class TiramisuOptionProperty(CommonTiramisuOption): class TiramisuOptionProperty(CommonTiramisuOption):
"""manager option's property""" """manager option's property"""
allow_optiondescription = True allow_optiondescription = True
allow_unrestraint = True
slave_need_index = False slave_need_index = False
def __init__(self, def __init__(self,
name, name,
path, path=None,
index, index=None,
subconfig, subconfig=None,
config_bag): config_bag=None):
super().__init__(name, super().__init__(name,
path, path,
index, index,
subconfig, subconfig,
config_bag) config_bag)
self.settings = config_bag.config.cfgimpl_get_settings() if config_bag:
self.settings = config_bag.config.cfgimpl_get_settings()
@count @count
def get(self, apply_requires=True): def get(self, apply_requires=True):
"""get properties for an option"""
self._get_option() self._get_option()
if apply_requires: if apply_requires:
self._test_slave_index() self._test_slave_index()
@ -340,6 +400,7 @@ class TiramisuOptionProperty(CommonTiramisuOption):
@count @count
def add(self, prop): def add(self, prop):
"""add new property for an option"""
self._get_option() self._get_option()
if prop in FORBIDDEN_SET_PROPERTIES: if prop in FORBIDDEN_SET_PROPERTIES:
raise ConfigError(_('cannot add this property: "{0}"').format( raise ConfigError(_('cannot add this property: "{0}"').format(
@ -354,6 +415,7 @@ class TiramisuOptionProperty(CommonTiramisuOption):
@count @count
def pop(self, prop): def pop(self, prop):
"""remove new property for an option"""
self._get_option() self._get_option()
props = self.settings.getproperties(self.path, props = self.settings.getproperties(self.path,
self.index, self.index,
@ -365,8 +427,7 @@ class TiramisuOptionProperty(CommonTiramisuOption):
@count @count
def reset(self): def reset(self):
"""reset all personalised properties """reset all personalised properties"""
"""
self._get_option() self._get_option()
self.settings.reset(opt=self.config_bag.option, self.settings.reset(opt=self.config_bag.option,
path=self.path) path=self.path)
@ -374,26 +435,26 @@ class TiramisuOptionProperty(CommonTiramisuOption):
class TiramisuOptionPermissive(CommonTiramisuOption): class TiramisuOptionPermissive(CommonTiramisuOption):
"""manager option's property""" """manager option's property"""
allow_unrestraint = True
allow_optiondescription = True allow_optiondescription = True
slave_need_index = False slave_need_index = False
def __init__(self, def __init__(self,
name, name,
path, path=None,
index, index=None,
subconfig, subconfig=None,
config_bag): config_bag=None):
super().__init__(name, super().__init__(name,
path, path,
index, index,
subconfig, subconfig,
config_bag) config_bag)
self.settings = config_bag.config.cfgimpl_get_settings() if config_bag:
self.settings = config_bag.config.cfgimpl_get_settings()
@count @count
def get(self): def get(self):
"""get permissive value for a specified path""" """get permissives value"""
if TIRAMISU_VERSION == 2: if TIRAMISU_VERSION == 2:
args = [self.setting_properties, self._path] args = [self.setting_properties, self._path]
else: else:
@ -402,6 +463,7 @@ class TiramisuOptionPermissive(CommonTiramisuOption):
@count @count
def set(self, permissives): def set(self, permissives):
"""set permissives value"""
if TIRAMISU_VERSION == 2: if TIRAMISU_VERSION == 2:
permissives = tuple(permissives) permissives = tuple(permissives)
path = self._path path = self._path
@ -418,29 +480,39 @@ class TiramisuOptionPermissive(CommonTiramisuOption):
@count @count
def reset(self, path): def reset(self, path):
"""reset all personalised permissive """reset all personalised permissive"""
"""
self.set(tuple()) self.set(tuple())
class TiramisuOptionInformation(CommonTiramisuOption): class TiramisuOptionInformation(CommonTiramisuOption):
allow_unrestraint = True """manage option informations"""
allow_optiondescription = True allow_optiondescription = True
slave_need_index = False slave_need_index = False
@count @count
def get(self, name, default=undefined): def get(self, name, default=undefined):
"""get information for a key name"""
option = self._get_option() option = self._get_option()
return option.impl_get_information(name, default) return option.impl_get_information(name, default)
@count
def set(self, name, value):
"""set information for a key name"""
self.config_bag.config.impl_set_information(name, value)
@count
def reset(self, name):
"""remove information for a key name"""
self.config_bag.config.impl_del_information(name)
class TiramisuOptionValue(CommonTiramisuOption): class TiramisuOptionValue(CommonTiramisuOption):
"""manager option's value""" """manager option's value"""
slave_need_index = False slave_need_index = False
allow_unrestraint = True
@count @count
def get(self): def get(self):
"""get option's value"""
self._get_option() self._get_option()
self._test_slave_index() self._test_slave_index()
settings = self.config_bag.config.cfgimpl_get_settings() settings = self.config_bag.config.cfgimpl_get_settings()
@ -475,8 +547,7 @@ class TiramisuOptionValue(CommonTiramisuOption):
@count @count
def _pop(self, index): def _pop(self, index):
"""pop value for a specified master values """pop value for a master option (only for master option)"""
"""
self._get_option() self._get_option()
self.config_bag.config.delattr(self.path, self.config_bag.config.delattr(self.path,
index, index,
@ -493,6 +564,7 @@ class TiramisuOptionValue(CommonTiramisuOption):
@count @count
def _len(self): def _len(self):
"""length of slave option (only for slave option)"""
self._get_option() self._get_option()
subconfig_path = self.path.rsplit('.', 1)[0] subconfig_path = self.path.rsplit('.', 1)[0]
if self.config_bag.setting_properties is not None: if self.config_bag.setting_properties is not None:
@ -516,6 +588,7 @@ class TiramisuOptionValue(CommonTiramisuOption):
@count @count
def _list(self): def _list(self):
"""all values available for an option (only for choiceoption)"""
return self.config_bag.option.impl_get_values(self.config_bag) return self.config_bag.option.impl_get_values(self.config_bag)
@ -528,15 +601,12 @@ def registers(registers, prefix):
class TiramisuOption(CommonTiramisu): class TiramisuOption(CommonTiramisu):
icon = '\u2937'
tmpl_help = ' {} {}: {}'
def __init__(self, def __init__(self,
name, name,
path, path=None,
index, index=None,
subconfig, subconfig=None,
config_bag): config_bag=None):
self._name = name self._name = name
self.subconfig = subconfig self.subconfig = subconfig
@ -546,14 +616,6 @@ class TiramisuOption(CommonTiramisu):
self.registers = {} self.registers = {}
registers(self.registers, self.__class__.__name__) registers(self.registers, self.__class__.__name__)
def _help(self):
txt = []
for module_name, module in self.registers.items():
module_doc = getdoc(module)
txt.append(self.tmpl_help.format(self.icon, module_name, module_doc))
txt.append(module(None, None).help)
return '\n'.join(txt)
def __getattr__(self, subfunc): def __getattr__(self, subfunc):
if subfunc in self.registers: if subfunc in self.registers:
return self.registers[subfunc](self._name, return self.registers[subfunc](self._name,
@ -561,8 +623,6 @@ class TiramisuOption(CommonTiramisu):
self.index, self.index,
self.subconfig, self.subconfig,
self.config_bag) self.config_bag)
elif subfunc == 'help':
return self._help()
elif subfunc == 'make_dict' and self._get_option().impl_is_optiondescription(): elif subfunc == 'make_dict' and self._get_option().impl_is_optiondescription():
return self._make_dict return self._make_dict
elif subfunc == 'list' and self._get_option().impl_is_optiondescription(): elif subfunc == 'list' and self._get_option().impl_is_optiondescription():
@ -578,6 +638,7 @@ class TiramisuOption(CommonTiramisu):
withvalue=undefined, withvalue=undefined,
withoption=None, withoption=None,
fullpath=False): fullpath=False):
"""return dict with path as key and value for an optiondescription (only for optiondescription)"""
return self.config_bag.config.getattr(self.path, return self.config_bag.config.getattr(self.path,
None, None,
self.config_bag).make_dict(config_bag=self.config_bag, self.config_bag).make_dict(config_bag=self.config_bag,
@ -587,13 +648,15 @@ class TiramisuOption(CommonTiramisu):
withvalue=withvalue) withvalue=withvalue)
@count @count
def group_type(self): def _group_type(self):
"""get type for an optiondescription (only for optiondescription)"""
return self._get_option().impl_get_group_type() return self._get_option().impl_get_group_type()
@count @count
def _list(self, def _list(self,
type='all', type='all',
group_type=None): group_type=None):
"""list options in an optiondescription (only for optiondescription)"""
if type == 'optiondescription': if type == 'optiondescription':
return self.config_bag.config.getattr(self.path, return self.config_bag.config.getattr(self.path,
None, None,
@ -608,29 +671,37 @@ class TiramisuOption(CommonTiramisu):
raise APIError(_('unknown list type {}').format(type)) raise APIError(_('unknown list type {}').format(type))
class TiramisuContext(object): class TiramisuContext(TiramisuHelp):
def __init__(self, def __init__(self,
config_bag): config_bag):
self.config_bag = config_bag self.config_bag = config_bag
self.registers = {}
registers(self.registers, self.__class__.__name__)
class TiramisuContextInformation(TiramisuContext): class TiramisuContextInformation(TiramisuContext):
"""manage configuration informations"""
@count @count
def get(self, name, default=undefined): def get(self, name, default=undefined):
"""get information for a key name"""
return self.config_bag.config.impl_get_information(name, default) return self.config_bag.config.impl_get_information(name, default)
@count @count
def set(self, name, value): def set(self, name, value):
"""set information for a key name"""
self.config_bag.config.impl_set_information(name, value) self.config_bag.config.impl_set_information(name, value)
@count @count
def reset(self, name): def reset(self, name):
"""remove information for a key name"""
self.config_bag.config.impl_del_information(name) self.config_bag.config.impl_del_information(name)
class TiramisuContextValue(TiramisuContext): class TiramisuContextValue(TiramisuContext):
"""manager value"""
@count @count
def mandatory_warnings(self): def mandatory_warnings(self):
"""return path of options with mandatory property without any value"""
return self.config_bag.config.cfgimpl_get_values().mandatory_warnings(self.config_bag) return self.config_bag.config.cfgimpl_get_values().mandatory_warnings(self.config_bag)
def set(self, def set(self,
@ -641,6 +712,7 @@ class TiramisuContextValue(TiramisuContext):
force_default=undefined, force_default=undefined,
force_default_if_same=undefined, force_default_if_same=undefined,
force_dont_change_value=undefined): force_dont_change_value=undefined):
"""set values for a GroupConfig or a MetaConfig"""
kwargs = {} kwargs = {}
if only_config is not undefined: if only_config is not undefined:
kwargs['only_config'] = only_config kwargs['only_config'] = only_config
@ -659,24 +731,31 @@ class TiramisuContextValue(TiramisuContext):
@count @count
def reset(self, def reset(self,
path): path):
"""reset value for a GroupConfig or a MetaConfig"""
self.config_bag.config.reset(path, self.config_bag) self.config_bag.config.reset(path, self.config_bag)
@count @count
def exportation(self): def exportation(self):
"""export all values"""
return self.config_bag.config.cfgimpl_get_values()._p_.exportation() return self.config_bag.config.cfgimpl_get_values()._p_.exportation()
@count @count
def importation(self, values): def importation(self, values):
"""import values"""
return self.config_bag.config.cfgimpl_get_values()._p_.importation(values) return self.config_bag.config.cfgimpl_get_values()._p_.importation(values)
class TiramisuContextOwner(TiramisuContext): class TiramisuContextOwner(TiramisuContext):
"""manager value"""
@count @count
def get(self): def get(self):
"""get default owner"""
return self.config_bag.config.cfgimpl_get_settings().getowner() return self.config_bag.config.cfgimpl_get_settings().getowner()
@count @count
def set(self, owner): def set(self, owner):
"""set default owner"""
try: try:
obj_owner = getattr(owners, owner) obj_owner = getattr(owners, owner)
except AttributeError: except AttributeError:
@ -686,14 +765,18 @@ class TiramisuContextOwner(TiramisuContext):
class TiramisuContextProperty(TiramisuContext): class TiramisuContextProperty(TiramisuContext):
"""manage configuration properties"""
@count @count
def read_only(self): def read_only(self):
"""set configuration to read only mode"""
settings = self.config_bag.config.cfgimpl_get_settings() settings = self.config_bag.config.cfgimpl_get_settings()
settings.read_only() settings.read_only()
self.config_bag.setting_properties = settings.get_context_properties() self.config_bag.setting_properties = settings.get_context_properties()
@count @count
def read_write(self): def read_write(self):
"""set configuration to read and write mode"""
settings = self.config_bag.config.cfgimpl_get_settings() settings = self.config_bag.config.cfgimpl_get_settings()
settings.read_write() settings.read_write()
# #FIXME ? # #FIXME ?
@ -703,6 +786,7 @@ class TiramisuContextProperty(TiramisuContext):
@count @count
def add(self, prop): def add(self, prop):
"""add a configuration property"""
props = self.get() props = self.get()
props.add(prop) props.add(prop)
self.set(frozenset(props)) self.set(frozenset(props))
@ -710,6 +794,7 @@ class TiramisuContextProperty(TiramisuContext):
@count @count
def pop(self, prop): def pop(self, prop):
"""remove a configuration property"""
props = self.get() props = self.get()
if prop in props: if prop in props:
props.remove(prop) props.remove(prop)
@ -718,68 +803,83 @@ class TiramisuContextProperty(TiramisuContext):
@count @count
def get(self): def get(self):
"""get all configuration properties"""
return set(self.config_bag.setting_properties) return set(self.config_bag.setting_properties)
@count @count
def set(self, props): def set(self, props):
"""personalise configuration properties"""
self.config_bag.config.cfgimpl_get_settings().set_context_properties(props) self.config_bag.config.cfgimpl_get_settings().set_context_properties(props)
self.config_bag.setting_properties = self.config_bag.config.cfgimpl_get_settings().get_context_properties() self.config_bag.setting_properties = self.config_bag.config.cfgimpl_get_settings().get_context_properties()
@count @count
def reset(self): def reset(self):
"""remove configuration properties"""
self.config_bag.config.cfgimpl_get_settings().reset() self.config_bag.config.cfgimpl_get_settings().reset()
@count @count
def exportation(self): def exportation(self):
"""export configuration properties"""
return self.config_bag.config.cfgimpl_get_settings()._p_.exportation() return self.config_bag.config.cfgimpl_get_settings()._p_.exportation()
@count @count
def importation(self, properties): def importation(self, properties):
"""import configuration properties"""
return self.config_bag.config.cfgimpl_get_settings()._p_.importation(properties) return self.config_bag.config.cfgimpl_get_settings()._p_.importation(properties)
class TiramisuContextPermissive(TiramisuContext): class TiramisuContextPermissive(TiramisuContext):
"""manage configuration permissives"""
@count
def get(self):
"""get configuration permissives"""
self.config_bag.config.cfgimpl_get_settings().get_context_permissive(permissives)
@count @count
def set(self, permissives): def set(self, permissives):
"""set configuration permissives"""
self.config_bag.config.cfgimpl_get_settings().set_context_permissive(permissives) self.config_bag.config.cfgimpl_get_settings().set_context_permissive(permissives)
@count @count
def exportation(self): def exportation(self):
"""export configuration permissives"""
return self.config_bag.config.cfgimpl_get_settings()._pp_.exportation() return self.config_bag.config.cfgimpl_get_settings()._pp_.exportation()
@count @count
def importation(self, permissives): def importation(self, permissives):
"""import configuration permissives"""
return self.config_bag.config.cfgimpl_get_settings()._pp_.importation(permissives) return self.config_bag.config.cfgimpl_get_settings()._pp_.importation(permissives)
class TiramisuContextOption(TiramisuContext): class TiramisuContextOption(TiramisuContext):
@count """manage option"""
def find_first(self,
name,
type='option'):
check_properties = self.config_bag.force_unrestraint or self.config_bag.force_unrestraint
return self.config_bag.config.find_first(byname=name,
type_=type,
config_bag=self.config_bag)
@count @count
def find(self, def find(self,
name, name,
type='option'): type='option',
return self.config_bag.config.find(byname=name, first=False):
type_=type, """find an option by name"""
config_bag=self.config_bag) if first:
return self.config_bag.config.find_first(byname=name,
type_=type,
config_bag=self.config_bag)
else:
return self.config_bag.config.find(byname=name,
type_=type,
config_bag=self.config_bag)
@count #@count
def get(self, path): #def get(self, path):
config_bag = self.config_bag.copy() # """"""
config_bag.validate = False # config_bag = self.config_bag.copy()
config_bag.force_unrestraint = True # config_bag.validate = False
config_bag.setting_properties = None # config_bag.force_unrestraint = True
return self.config_bag.config.unwrap_from_path(path, # config_bag.setting_properties = None
config_bag) # return self.config_bag.config.unwrap_from_path(path,
# config_bag)
@count @count
def make_dict(self, def make_dict(self,
@ -787,6 +887,7 @@ class TiramisuContextOption(TiramisuContext):
withvalue=undefined, withvalue=undefined,
withoption=None, withoption=None,
fullpath=False): fullpath=False):
"""return dict with path as key and value"""
return self.config_bag.config.make_dict(self.config_bag, return self.config_bag.config.make_dict(self.config_bag,
flatten=flatten, flatten=flatten,
fullpath=fullpath, fullpath=fullpath,
@ -798,6 +899,7 @@ class TiramisuContextOption(TiramisuContext):
type='all', type='all',
group_type=None, group_type=None,
recursive=False): recursive=False):
"""list content of an optiondescription"""
if type == 'optiondescription': if type == 'optiondescription':
if recursive: if recursive:
raise APIError(_('not implemented yet')) raise APIError(_('not implemented yet'))
@ -818,16 +920,27 @@ class TiramisuContextOption(TiramisuContext):
class TiramisuContextConfig(TiramisuContext): class TiramisuContextConfig(TiramisuContext):
def find_first(self, """configuration methods"""
name, def find(self,
byvalue=undefined): name,
return self.config_bag.config.find_firsts(byname=name, byvalue=undefined,
byvalue=byvalue, first=False):
config_bag=self.config_bag) """find a path from option name and optionnaly a value to MetaConfig or GroupConfig"""
if first:
return self.config_bag.config.find_firsts(byname=name,
byvalue=byvalue,
config_bag=self.config_bag)
else:
raise APIError('not implemented yet')
class TiramisuDispatcherConfig(TiramisuContextConfig): class TiramisuDispatcher:
pass
class TiramisuDispatcherConfig(TiramisuDispatcher, TiramisuContextConfig):
def __call__(self, path): def __call__(self, path):
"""select a child Tiramisu configuration (only with MetaConfig or GroupConfig)"""
config = self.config_bag.config config = self.config_bag.config
if path is None: if path is None:
return TiramisuAPI(config, return TiramisuAPI(config,
@ -841,8 +954,10 @@ class TiramisuDispatcherConfig(TiramisuContextConfig):
force_unrestraint=self.config_bag.force_unrestraint) force_unrestraint=self.config_bag.force_unrestraint)
class TiramisuDispatcherOption(TiramisuContextOption): class TiramisuDispatcherOption(TiramisuDispatcher, TiramisuContextOption):
subhelp = TiramisuOption
def __call__(self, path, index=None): def __call__(self, path, index=None):
"""select a option (index only for slave option)"""
config_bag = self.config_bag.copy() config_bag = self.config_bag.copy()
validate = not config_bag.force_unrestraint validate = not config_bag.force_unrestraint
if not validate: if not validate:
@ -856,9 +971,7 @@ class TiramisuDispatcherOption(TiramisuContextOption):
config_bag) config_bag)
class TiramisuAPI(object): class TiramisuAPI(TiramisuHelp):
icon = '\u2937'
tmpl_help = ' {} {}: {}'
def __init__(self, def __init__(self,
config, config,
@ -880,8 +993,6 @@ class TiramisuAPI(object):
return TiramisuAPI(config=self._config, return TiramisuAPI(config=self._config,
force_permissive=self.force_permissive, force_permissive=self.force_permissive,
force_unrestraint=True) force_unrestraint=True)
elif subfunc == 'help':
return self._help()
elif subfunc in self.registers: elif subfunc in self.registers:
config_bag = ConfigBag(config=self._config, config_bag = ConfigBag(config=self._config,
force_permissive=self.force_permissive, force_permissive=self.force_permissive,
@ -890,14 +1001,6 @@ class TiramisuAPI(object):
else: else:
raise APIError(_('please specify a valid sub function ({})').format(subfunc)) raise APIError(_('please specify a valid sub function ({})').format(subfunc))
def _help(self):
txt = ['[forcepermissive]']
for module_name, module in self.registers.items():
module_doc = getdoc(module)
txt.append(self.tmpl_help.format(self.icon, module_name, module_doc))
txt.append(module(None, None).help)
return '\n'.join(txt)
@count @count
def getapi(config): def getapi(config):

View File

@ -269,7 +269,10 @@ forbidden_owners = (owners.default, owners.forced, owners.meta)
# ____________________________________________________________ # ____________________________________________________________
class Undefined(object): class Undefined(object):
pass def __str__(self):
return 'Undefined'
__repr__ = __str__
undefined = Undefined() undefined = Undefined()