From c3be5e82ba716d6df95b6d7191ff8e1b6a1e8484 Mon Sep 17 00:00:00 2001 From: Emmanuel Garette Date: Sat, 7 Apr 2018 20:15:19 +0200 Subject: [PATCH] update help() in api --- test/auto/{test_owner.py => test_auto.py} | 32 +- test/test_config.py | 4 +- test/test_config_api.py | 21 +- test/test_dyn_optiondescription.py | 4 +- test/test_metaconfig.py | 30 +- test/test_option_setting.py | 4 +- test/test_parsing_group.py | 2 +- tiramisu/api.py | 343 ++++++++++++++-------- tiramisu/setting.py | 5 +- 9 files changed, 281 insertions(+), 164 deletions(-) rename test/auto/{test_owner.py => test_auto.py} (99%) diff --git a/test/auto/test_owner.py b/test/auto/test_auto.py similarity index 99% rename from test/auto/test_owner.py rename to test/auto/test_auto.py index 3923715..37d7640 100644 --- a/test/auto/test_owner.py +++ b/test/auto/test_auto.py @@ -17,7 +17,7 @@ ICON = u'\u2937' OPTIONS_TYPE = {'str': {'type': str, 'option': StrOption} } -PROPERTIES = ['hidden', 'disabled'] +PROPERTIES = ['hidden', 'disabled', 'mandatory'] PROPERTIES_LIST = ['prop1', 'prop2'] OWNER = 'user' @@ -1068,7 +1068,7 @@ def autocheck_option_get(api, pathread, pathwrite, confread, confwrite, **kwargs name = pathread.rsplit('.', 1)[1] else: name = pathread - assert api.option.get(pathread).impl_getname() == name + assert api.unrestraint.option(pathread).option.name() == name @autocheck @@ -1088,28 +1088,28 @@ def autocheck_find(api, pathread, pathwrite, confread, confwrite, **kwargs): name = pathread.rsplit('.', 1)[1] else: name = pathread - option = _getoption(api.option.get(pathread)) + option = _getoption(api.unrestraint.option(pathread).option.get()) def do(conf): 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.forcepermissive.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(name, first=True)) elif kwargs.get('permissive', False): - raises(AttributeError, "api.config(conf).option.find_first(name)") - assert option == _getoption(api.forcepermissive.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(name, first=True)) else: - raises(AttributeError, "api.config(conf).option.find_first(name)") - raises(AttributeError, "api.forcepermissive.config(conf).option.find_first(name)") - assert option == _getoption(api.unrestraint.config(conf).option.find_first(name)) + raises(AttributeError, "api.config(conf).option.find(name, first=True)") + raises(AttributeError, "api.forcepermissive.config(conf).option.find(name, first=True)") + assert option == _getoption(api.unrestraint.config(conf).option.find(name, first=True)) 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') do(confread) if confread != 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(): dico = {} dico_value = {} @@ -1132,7 +1132,7 @@ def check_all(cfg, paths, path, meta, multi, default, default_multi, require, co is_master = False dyns = [] has_value = False - for cpath, options in paths.items(): + for cpath, options in paths_.items(): if options is None: break if '.' in cpath: @@ -1172,7 +1172,7 @@ def check_all(cfg, paths, path, meta, multi, default, default_multi, require, co kwargs['default'] = None if is_dyn and dyns: idx = 0 - for cpath in list(paths.keys())[len(dyns):]: + for cpath in list(paths_.keys())[len(dyns):]: if dyns[idx]: dico[cpath] = default_value if symlink: @@ -1227,7 +1227,7 @@ def check_all(cfg, paths, path, meta, multi, default, default_multi, require, co dico[cpath + 'extraoptconsistency'] = value dico_value[cpath + 'extraoptconsistency'] = value 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'): second_path = cpath.rsplit('.', 1)[0] + '.second' third_path = cpath.rsplit('.', 1)[0] + '.third' @@ -1698,6 +1698,8 @@ def paths(request): def test_options(paths): def get_kwargs_option(options, kwargs, od=False): + if options.get('mandatory', False): + kwargs['mandatory'] = True if options.get('hidden', False) is True: kwargs['permissive'] = True if not od: diff --git a/test/test_config.py b/test/test_config.py index bacf049..6fc378e 100644 --- a/test/test_config.py +++ b/test/test_config.py @@ -163,8 +163,8 @@ def test_config_impl_get_path_by_opt(): descr = make_description() config = Config(descr) api = getapi(config) - dummy = api.option.get('gc.dummy') - boo = api.option.get('bool') + dummy = api.option('gc.dummy').option.get() + boo = api.option('bool').option.get() unknown = IntOption('test', '') unknown assert config.cfgimpl_get_description().impl_get_path_by_opt(boo) == 'bool' diff --git a/test/test_config_api.py b/test/test_config_api.py index 54e466d..6d15b9b 100644 --- a/test/test_config_api.py +++ b/test/test_config_api.py @@ -165,17 +165,17 @@ def test_find_in_config(): api.permissive.set(frozenset(['hidden'])) ret = api.option.find('dummy') 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') - _is_same_opt(ret, api.option.get('gc.dummy')) + ret = api.option.find('dummy', first=True) + _is_same_opt(ret, api.option('gc.dummy').option.get()) # ret = api.option.find('float') assert len(ret) == 2 - _is_same_opt(ret[0], api.option.get('gc.float')) - _is_same_opt(ret[1], api.option.get('float')) + _is_same_opt(ret[0], api.option('gc.float').option.get()) + _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='dummy'), conf.unwrap_from_path('gc.dummy')) #_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, "DomainnameOption('a', '', multi=True, default_multi='string')") 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) diff --git a/test/test_dyn_optiondescription.py b/test/test_dyn_optiondescription.py index 7e0d60e..9cecec3 100644 --- a/test/test_dyn_optiondescription.py +++ b/test/test_dyn_optiondescription.py @@ -639,8 +639,8 @@ def test_find_dyndescription_context(): od2 = OptionDescription('od', '', [od]) api = getapi(Config(od2)) api.option('od.dodval1.stval1').value.set('yes') - assert api.option.find_first('stval1', type='value') == "yes" - assert isinstance(api.option.find_first('stval1', type='option'), DynSymLinkOption) + assert api.option.find('stval1', type='value', first=True) == "yes" + 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'] #opts = api.option.find(byvalue='yes') #assert len(opts) == 1 diff --git a/test/test_metaconfig.py b/test/test_metaconfig.py index 8406c65..2e2a359 100644 --- a/test/test_metaconfig.py +++ b/test/test_metaconfig.py @@ -127,7 +127,7 @@ def test_contexts(): def test_find(): api = make_metaconfig() 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, 'od1.i2': 1, 'od1.i5': [2]} @@ -203,15 +203,15 @@ def test_meta_meta_set(): conf1 = meta.getconfig('conf1') 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 [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) - assert [conf1, conf2] == api.config.find_first('i1').cfgimpl_get_children() - assert [conf2] == api.config.find_first('i1', byvalue=7).cfgimpl_get_children() - assert [conf1] == api.config.find_first('i1', byvalue=8).cfgimpl_get_children() - assert [conf1, conf2] == api.config.find_first('i5', byvalue=2).cfgimpl_get_children() - raises(AttributeError, "api.config.find_first('i1', byvalue=10)") - raises(AttributeError, "api.config.find_first('not', byvalue=10)") - raises(AttributeError, "api.config.find_first('i6')") + assert [conf1, conf2] == api.config.find('i1', first=True).cfgimpl_get_children() + assert [conf2] == api.config.find('i1', byvalue=7, first=True).cfgimpl_get_children() + assert [conf1] == api.config.find('i1', byvalue=8, first=True).cfgimpl_get_children() + assert [conf1, conf2] == api.config.find('i5', byvalue=2, first=True).cfgimpl_get_children() + raises(AttributeError, "api.config.find('i1', byvalue=10, first=True)") + raises(AttributeError, "api.config.find('not', byvalue=10, first=True)") + 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_if_same=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') grp = GroupConfig([conf1, conf2]) 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(): @@ -295,13 +295,13 @@ def test_meta_master_slaves(): conf2 = Config(od, session_id='conf2') api = getapi(MetaConfig([conf1, conf2])) api.property.read_only() - assert [conf1, conf2] == api.config.find_first('ip_admin_eth0').cfgimpl_get_children() - assert [conf1, conf2] == api.config.find_first('netmask_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('netmask_admin_eth0', first=True).cfgimpl_get_children() api.property.read_write() - raises(AttributeError, "api.config.find_first('netmask_admin_eth0')") - assert [conf1, conf2] == api.unrestraint.config.find_first('netmask_admin_eth0').cfgimpl_get_children() + raises(AttributeError, "api.config.find('netmask_admin_eth0', first=True)") + assert [conf1, conf2] == api.unrestraint.config.find('netmask_admin_eth0', first=True).cfgimpl_get_children() 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(): diff --git a/test/test_option_setting.py b/test/test_option_setting.py index 9993e06..e568a7a 100644 --- a/test/test_option_setting.py +++ b/test/test_option_setting.py @@ -384,8 +384,8 @@ def test_access_by_get(): descr = make_description() api = getapi(Config(descr)) raises(AttributeError, "api.option.find('idontexist')") - assert api.option.find_first('wantref', type='value') is False - assert api.option.find_first('dummy', type='value') is False + assert api.option.find('wantref', type='value', first=True) is False + assert api.option.find('dummy', type='value', first=True) is False def test_access_by_get_whith_hide(): diff --git a/test/test_parsing_group.py b/test/test_parsing_group.py index 4777587..bdf3c72 100644 --- a/test/test_parsing_group.py +++ b/test/test_parsing_group.py @@ -52,7 +52,7 @@ def test_base_config(): api.property.read_write() 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.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, 'general.serveur_ntp': [], 'interface1.ip_admin_eth0.ip_admin_eth0': None, 'general.mode_conteneur_actif': False, 'general.time_zone': 'Paris', diff --git a/tiramisu/api.py b/tiramisu/api.py index 4c8f03c..4a8a892 100644 --- a/tiramisu/api.py +++ b/tiramisu/api.py @@ -14,7 +14,7 @@ # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # ____________________________________________________________ -from inspect import ismethod, getdoc +from inspect import ismethod, getdoc, signature from .error import APIError, ConfigError, SlaveError from .i18n import _ from .setting import ConfigBag, owners, undefined, FORBIDDEN_SET_PROPERTIES @@ -36,6 +36,9 @@ COUNT_TIME = False #COUNT_TIME = {} +EXCLUDE_HELP = ('help', '_get_option', '_test_slave_index') + + def count(func): global MOD_COUNT_TIME class_name = func.__str__().split()[1].split('.')[0] @@ -80,8 +83,76 @@ def display_count(): 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 + registers = {} def _get_option(self): option = self.config_bag.option @@ -108,27 +179,22 @@ class CommonTiramisu(object): class CommonTiramisuOption(CommonTiramisu): - icon = '\u2937' - tmpl_help = u' {} {}: {}' - allow_unrestraint = False allow_optiondescription = False slave_need_index = True def __init__(self, name, - path, - index, - subconfig, - config_bag): + path=None, + index=None, + subconfig=None, + config_bag=None): self.path = path self.index = index self.config_bag = config_bag self._name = name self.subconfig = subconfig - if self.slave_need_index: + if config_bag is not None and self.slave_need_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): 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'): 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): - if name == 'help': - return self._help() + if not hasattr(CommonTiramisuOption, name): + raise APIError(_('unknown method {}').format(name)) else: - if not hasattr(CommonTiramisuOption, 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) + super().__getattribute__(name) class TiramisuOptionOption(CommonTiramisuOption): - """get information from an option""" - allow_unrestraint = True + """manage option""" allow_optiondescription = True slave_need_index = False @count def get(self): + """get Tiramisu option""" return self._get_option() @count @@ -203,41 +253,49 @@ class TiramisuOptionOption(CommonTiramisuOption): @count def doc(self): + """get option document""" option = self._get_option() return option.impl_get_display_name() @count def name(self): + """get option name""" self._get_option() return self._name @count def _default(self): + """get default value for an option (not for optiondescription)""" option = self._get_option() return option.impl_getdefault() @count def _defaultmulti(self): + """get default value when added a value for a multi option (not for optiondescription)""" option = self._get_option() return option.impl_getdefault_multi() @count def has_dependency(self, self_is_dep=True): + """test if option has dependency""" option = self._get_option() return option.impl_has_dependency(self_is_dep) @count def _consistencies(self): + """get consistencies for an option (not for optiondescription)""" option = self._get_option() return option.get_consistencies() @count def _callbacks(self): + """get callbacks for an option (not for optiondescription)""" option = self._get_option() return option.impl_get_callback() @count def requires(self): + """get requires for an option""" option = self._get_option() return option.impl_getrequires() @@ -251,26 +309,27 @@ class TiramisuOptionOption(CommonTiramisuOption): raise APIError(_('{} is unknown').format(name)) def isoptiondescription(self): + """test if option is an optiondescription""" return self._get_option().impl_is_optiondescription() class TiramisuOptionOwner(CommonTiramisuOption): """manager option's owner""" - allow_unrestraint = True def __init__(self, name, - path, - index, - subconfig, - config_bag): + path=None, + index=None, + subconfig=None, + config_bag=None): super().__init__(name, path, index, subconfig, config_bag) - self.values = self.config_bag.config.cfgimpl_get_values() + if config_bag: + self.values = self.config_bag.config.cfgimpl_get_values() @count def get(self): @@ -309,24 +368,25 @@ class TiramisuOptionOwner(CommonTiramisuOption): class TiramisuOptionProperty(CommonTiramisuOption): """manager option's property""" allow_optiondescription = True - allow_unrestraint = True slave_need_index = False def __init__(self, name, - path, - index, - subconfig, - config_bag): + path=None, + index=None, + subconfig=None, + config_bag=None): super().__init__(name, path, index, subconfig, config_bag) - self.settings = config_bag.config.cfgimpl_get_settings() + if config_bag: + self.settings = config_bag.config.cfgimpl_get_settings() @count def get(self, apply_requires=True): + """get properties for an option""" self._get_option() if apply_requires: self._test_slave_index() @@ -340,6 +400,7 @@ class TiramisuOptionProperty(CommonTiramisuOption): @count def add(self, prop): + """add new property for an option""" self._get_option() if prop in FORBIDDEN_SET_PROPERTIES: raise ConfigError(_('cannot add this property: "{0}"').format( @@ -354,6 +415,7 @@ class TiramisuOptionProperty(CommonTiramisuOption): @count def pop(self, prop): + """remove new property for an option""" self._get_option() props = self.settings.getproperties(self.path, self.index, @@ -365,8 +427,7 @@ class TiramisuOptionProperty(CommonTiramisuOption): @count def reset(self): - """reset all personalised properties - """ + """reset all personalised properties""" self._get_option() self.settings.reset(opt=self.config_bag.option, path=self.path) @@ -374,26 +435,26 @@ class TiramisuOptionProperty(CommonTiramisuOption): class TiramisuOptionPermissive(CommonTiramisuOption): """manager option's property""" - allow_unrestraint = True allow_optiondescription = True slave_need_index = False def __init__(self, name, - path, - index, - subconfig, - config_bag): + path=None, + index=None, + subconfig=None, + config_bag=None): super().__init__(name, path, index, subconfig, config_bag) - self.settings = config_bag.config.cfgimpl_get_settings() + if config_bag: + self.settings = config_bag.config.cfgimpl_get_settings() @count def get(self): - """get permissive value for a specified path""" + """get permissives value""" if TIRAMISU_VERSION == 2: args = [self.setting_properties, self._path] else: @@ -402,6 +463,7 @@ class TiramisuOptionPermissive(CommonTiramisuOption): @count def set(self, permissives): + """set permissives value""" if TIRAMISU_VERSION == 2: permissives = tuple(permissives) path = self._path @@ -418,29 +480,39 @@ class TiramisuOptionPermissive(CommonTiramisuOption): @count def reset(self, path): - """reset all personalised permissive - """ + """reset all personalised permissive""" self.set(tuple()) class TiramisuOptionInformation(CommonTiramisuOption): - allow_unrestraint = True + """manage option informations""" allow_optiondescription = True slave_need_index = False @count def get(self, name, default=undefined): + """get information for a key name""" option = self._get_option() 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): """manager option's value""" slave_need_index = False - allow_unrestraint = True @count def get(self): + """get option's value""" self._get_option() self._test_slave_index() settings = self.config_bag.config.cfgimpl_get_settings() @@ -475,8 +547,7 @@ class TiramisuOptionValue(CommonTiramisuOption): @count 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.config_bag.config.delattr(self.path, index, @@ -493,6 +564,7 @@ class TiramisuOptionValue(CommonTiramisuOption): @count def _len(self): + """length of slave option (only for slave option)""" self._get_option() subconfig_path = self.path.rsplit('.', 1)[0] if self.config_bag.setting_properties is not None: @@ -516,6 +588,7 @@ class TiramisuOptionValue(CommonTiramisuOption): @count def _list(self): + """all values available for an option (only for choiceoption)""" return self.config_bag.option.impl_get_values(self.config_bag) @@ -528,15 +601,12 @@ def registers(registers, prefix): class TiramisuOption(CommonTiramisu): - icon = '\u2937' - tmpl_help = ' {} {}: {}' - def __init__(self, name, - path, - index, - subconfig, - config_bag): + path=None, + index=None, + subconfig=None, + config_bag=None): self._name = name self.subconfig = subconfig @@ -546,14 +616,6 @@ class TiramisuOption(CommonTiramisu): self.registers = {} 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): if subfunc in self.registers: return self.registers[subfunc](self._name, @@ -561,8 +623,6 @@ class TiramisuOption(CommonTiramisu): self.index, self.subconfig, self.config_bag) - elif subfunc == 'help': - return self._help() elif subfunc == 'make_dict' and self._get_option().impl_is_optiondescription(): return self._make_dict elif subfunc == 'list' and self._get_option().impl_is_optiondescription(): @@ -578,6 +638,7 @@ class TiramisuOption(CommonTiramisu): withvalue=undefined, withoption=None, fullpath=False): + """return dict with path as key and value for an optiondescription (only for optiondescription)""" return self.config_bag.config.getattr(self.path, None, self.config_bag).make_dict(config_bag=self.config_bag, @@ -587,13 +648,15 @@ class TiramisuOption(CommonTiramisu): withvalue=withvalue) @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() @count def _list(self, type='all', group_type=None): + """list options in an optiondescription (only for optiondescription)""" if type == 'optiondescription': return self.config_bag.config.getattr(self.path, None, @@ -608,29 +671,37 @@ class TiramisuOption(CommonTiramisu): raise APIError(_('unknown list type {}').format(type)) -class TiramisuContext(object): +class TiramisuContext(TiramisuHelp): def __init__(self, config_bag): self.config_bag = config_bag + self.registers = {} + registers(self.registers, self.__class__.__name__) class TiramisuContextInformation(TiramisuContext): + """manage configuration informations""" @count def get(self, name, default=undefined): + """get information for a key name""" return self.config_bag.config.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 TiramisuContextValue(TiramisuContext): + """manager value""" @count 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) def set(self, @@ -641,6 +712,7 @@ class TiramisuContextValue(TiramisuContext): force_default=undefined, force_default_if_same=undefined, force_dont_change_value=undefined): + """set values for a GroupConfig or a MetaConfig""" kwargs = {} if only_config is not undefined: kwargs['only_config'] = only_config @@ -659,24 +731,31 @@ class TiramisuContextValue(TiramisuContext): @count def reset(self, path): + """reset value for a GroupConfig or a MetaConfig""" self.config_bag.config.reset(path, self.config_bag) @count def exportation(self): + """export all values""" return self.config_bag.config.cfgimpl_get_values()._p_.exportation() @count def importation(self, values): + """import values""" return self.config_bag.config.cfgimpl_get_values()._p_.importation(values) class TiramisuContextOwner(TiramisuContext): + """manager value""" + @count def get(self): + """get default owner""" return self.config_bag.config.cfgimpl_get_settings().getowner() @count def set(self, owner): + """set default owner""" try: obj_owner = getattr(owners, owner) except AttributeError: @@ -686,14 +765,18 @@ class TiramisuContextOwner(TiramisuContext): class TiramisuContextProperty(TiramisuContext): + """manage configuration properties""" + @count def read_only(self): + """set configuration to read only mode""" settings = self.config_bag.config.cfgimpl_get_settings() settings.read_only() self.config_bag.setting_properties = settings.get_context_properties() @count def read_write(self): + """set configuration to read and write mode""" settings = self.config_bag.config.cfgimpl_get_settings() settings.read_write() # #FIXME ? @@ -703,6 +786,7 @@ class TiramisuContextProperty(TiramisuContext): @count def add(self, prop): + """add a configuration property""" props = self.get() props.add(prop) self.set(frozenset(props)) @@ -710,6 +794,7 @@ class TiramisuContextProperty(TiramisuContext): @count def pop(self, prop): + """remove a configuration property""" props = self.get() if prop in props: props.remove(prop) @@ -718,68 +803,83 @@ class TiramisuContextProperty(TiramisuContext): @count def get(self): + """get all configuration properties""" return set(self.config_bag.setting_properties) @count def set(self, props): + """personalise configuration properties""" 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() @count def reset(self): + """remove configuration properties""" self.config_bag.config.cfgimpl_get_settings().reset() @count def exportation(self): + """export configuration properties""" return self.config_bag.config.cfgimpl_get_settings()._p_.exportation() @count def importation(self, properties): + """import configuration properties""" return self.config_bag.config.cfgimpl_get_settings()._p_.importation(properties) 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 def set(self, permissives): + """set configuration permissives""" self.config_bag.config.cfgimpl_get_settings().set_context_permissive(permissives) @count def exportation(self): + """export configuration permissives""" return self.config_bag.config.cfgimpl_get_settings()._pp_.exportation() @count def importation(self, permissives): + """import configuration permissives""" return self.config_bag.config.cfgimpl_get_settings()._pp_.importation(permissives) class TiramisuContextOption(TiramisuContext): - @count - 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) + """manage option""" @count def find(self, name, - type='option'): - return self.config_bag.config.find(byname=name, - type_=type, - config_bag=self.config_bag) + type='option', + first=False): + """find an option by name""" + 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 - def get(self, path): - config_bag = self.config_bag.copy() - config_bag.validate = False - config_bag.force_unrestraint = True - config_bag.setting_properties = None - return self.config_bag.config.unwrap_from_path(path, - config_bag) + #@count + #def get(self, path): + # """""" + # config_bag = self.config_bag.copy() + # config_bag.validate = False + # config_bag.force_unrestraint = True + # config_bag.setting_properties = None + # return self.config_bag.config.unwrap_from_path(path, + # config_bag) @count def make_dict(self, @@ -787,6 +887,7 @@ class TiramisuContextOption(TiramisuContext): withvalue=undefined, withoption=None, fullpath=False): + """return dict with path as key and value""" return self.config_bag.config.make_dict(self.config_bag, flatten=flatten, fullpath=fullpath, @@ -798,6 +899,7 @@ class TiramisuContextOption(TiramisuContext): type='all', group_type=None, recursive=False): + """list content of an optiondescription""" if type == 'optiondescription': if recursive: raise APIError(_('not implemented yet')) @@ -818,16 +920,27 @@ class TiramisuContextOption(TiramisuContext): class TiramisuContextConfig(TiramisuContext): - def find_first(self, - name, - byvalue=undefined): - return self.config_bag.config.find_firsts(byname=name, - byvalue=byvalue, - config_bag=self.config_bag) + """configuration methods""" + def find(self, + name, + byvalue=undefined, + first=False): + """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): + """select a child Tiramisu configuration (only with MetaConfig or GroupConfig)""" config = self.config_bag.config if path is None: return TiramisuAPI(config, @@ -841,8 +954,10 @@ class TiramisuDispatcherConfig(TiramisuContextConfig): force_unrestraint=self.config_bag.force_unrestraint) -class TiramisuDispatcherOption(TiramisuContextOption): +class TiramisuDispatcherOption(TiramisuDispatcher, TiramisuContextOption): + subhelp = TiramisuOption def __call__(self, path, index=None): + """select a option (index only for slave option)""" config_bag = self.config_bag.copy() validate = not config_bag.force_unrestraint if not validate: @@ -856,9 +971,7 @@ class TiramisuDispatcherOption(TiramisuContextOption): config_bag) -class TiramisuAPI(object): - icon = '\u2937' - tmpl_help = ' {} {}: {}' +class TiramisuAPI(TiramisuHelp): def __init__(self, config, @@ -880,8 +993,6 @@ class TiramisuAPI(object): return TiramisuAPI(config=self._config, force_permissive=self.force_permissive, force_unrestraint=True) - elif subfunc == 'help': - return self._help() elif subfunc in self.registers: config_bag = ConfigBag(config=self._config, force_permissive=self.force_permissive, @@ -890,14 +1001,6 @@ class TiramisuAPI(object): else: 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 def getapi(config): diff --git a/tiramisu/setting.py b/tiramisu/setting.py index 20ac032..ce16917 100644 --- a/tiramisu/setting.py +++ b/tiramisu/setting.py @@ -269,7 +269,10 @@ forbidden_owners = (owners.default, owners.forced, owners.meta) # ____________________________________________________________ class Undefined(object): - pass + def __str__(self): + return 'Undefined' + + __repr__ = __str__ undefined = Undefined()