diff --git a/test/api/test_owner.py b/test/api/test_owner.py index 8a5ea94..679e864 100644 --- a/test/api/test_owner.py +++ b/test/api/test_owner.py @@ -138,18 +138,15 @@ def autocheck_value(api, path, **kwargs): if not kwargs.get('permissive', False) and not kwargs.get('propertyerror', False): if ismaster: raises(APIError, "api.option(path, 0).value.set(first_value[0])") - api.option(path).value.append(first_value[0]) + api.option(path).value.set([first_value[0]]) elif isslave: - #FIXME - print(api.option(path).value.append(first_value[0])) - raises(PropertiesOptionError, "api.option(path).value.append(first_value[0])") api.option(path, 0).value.set(first_value[0]) raise Exception('pouet') else: api.option(path).value.set(first_value) else: if ismaster: - raises(PropertiesOptionError, "api.option(path).value.append(first_value[0])") + raises(PropertiesOptionError, "api.option(path).value.set([first_value[0]])") elif isslave: raises(PropertiesOptionError, "api.option(path, 0).value.set(first_value[0])") else: @@ -180,31 +177,30 @@ def autocheck_value(api, path, **kwargs): if ismaster: raises(APIError, "api.unrestraint.option(path).value.set(second_value[1])") elif isslave: - raises(APIError, "api.unrestraint.option(path).value.append(second_value[1])") + raises(APIError, "api.unrestraint.option(path).value.set([first_value[0], second_value[1]])") else: raises(APIError, "api.unrestraint.option(path).value.set(second_value)") if not kwargs.get('permissive', False) and not kwargs.get('propertyerror', False): if ismaster: raises(APIError, "api.forcepermissive.option(path, 1).value.set(second_value[1])") - api.forcepermissive.option(path).value.append(second_value[1]) + api.forcepermissive.option(path).value.set([first_value[0], second_value[1]]) elif isslave: #FIXME - raises(PropertiesOptionError, "api.forcepermissive.option(path).value.append(second_value[1])") + raises(PropertiesOptionError, "api.forcepermissive.option(path).value.set([first_value[0], second_value[1]])") api.option(path, 1).value.set(second_value[1]) raise Exception('ca entre ici') else: api.option(path).value.set(second_value) elif kwargs.get('permissive', False): if ismaster: - api.forcepermissive.option(path).value.append(second_value[0]) - api.forcepermissive.option(path).value.append(second_value[1]) + api.forcepermissive.option(path).value.set([first_value[0], second_value[1]]) elif isslave: api.forcepermissive.option(path, 1).value.set(second_value[1]) else: api.forcepermissive.option(path).value.set(first_value) else: if ismaster: - raises(PropertiesOptionError, "api.forcepermissive.option(path).value.append(first_value[0])") + raises(PropertiesOptionError, "api.forcepermissive.option(path).value.set([first_value[0]])") elif isslave: raises(PropertiesOptionError, "api.forcepermissive.option(path, 0).value.set(first_value[0])") else: @@ -240,15 +236,8 @@ def autocheck_value(api, path, **kwargs): @autocheck def autocheck_reset_value(api, path, **kwargs): # check if is a multi, a master or a slave - if not kwargs.get('propertyerror', False): - multi = api.forcepermissive.option(path).option.ismulti() - ismaster = api.forcepermissive.option(path).option.ismaster() - isslave = api.forcepermissive.option(path).option.isslave() - else: - raises(PropertiesOptionError, "api.forcepermissive.option(path).option.ismulti()") - multi = api.unrestraint.option(path).option.ismulti() - ismaster = api.unrestraint.option(path).option.ismaster() - isslave = api.unrestraint.option(path).option.isslave() + multi = api.unrestraint.option(path).option.ismulti() + isslave = api.unrestraint.option(path).option.isslave() # set default value (different if value is multi or not) if not multi: @@ -337,14 +326,8 @@ def autocheck_property(api, path, **kwargs): """get property from path """ # check if is a multi or a slave - if not kwargs.get('propertyerror', False): - multi = api.forcepermissive.option(path).option.ismulti() - isslave = api.forcepermissive.option(path).option.isslave() - else: - raises(PropertiesOptionError, "api.forcepermissive.option(path).option.ismulti()") - raises(PropertiesOptionError, "api.forcepermissive.option(path).option.isslave()") - multi = api.unrestraint.option(path).option.ismulti() - isslave = api.unrestraint.option(path).option.isslave() + multi = api.unrestraint.option(path).option.ismulti() + isslave = api.unrestraint.option(path).option.isslave() # define properties properties = ['prop1', 'prop2'] @@ -367,7 +350,10 @@ def autocheck_property(api, path, **kwargs): assert set(api.option(path, 0).property.get()) == set(default_props) assert set(api.option(path, 1).property.get()) == set(default_props) else: - raises(PropertiesOptionError, "api.option(path).property.get()") + if not isslave: + raises(PropertiesOptionError, "api.option(path).property.get()") + else: + raises(PropertiesOptionError, "api.option(path, 0).property.get()") # get properties with permissive if not isslave: @@ -390,17 +376,21 @@ def autocheck_property(api, path, **kwargs): if not kwargs.get('permissive', False) and not kwargs.get('propertyerror', False): api.option(path).property.set(properties) else: - raises(PropertiesOptionError, "api.option(path).property.set(properties)") + if not isslave: + raises(PropertiesOptionError, "api.option(path).property.set(properties)") + else: + raises(PropertiesOptionError, "api.option(path, 0).property.set(properties)") # check properties after set without permissive if not kwargs.get('permissive', False) and not kwargs.get('propertyerror', False): assert set(api.option(path).property.get()) == set(properties) assert set(api.forcepermissive.option(path).property.get()) == set(properties) elif kwargs.get('permissive', False): - raises(PropertiesOptionError, "api.option(path).property.get()") if not isslave: + raises(PropertiesOptionError, "api.option(path).property.get()") assert set(api.forcepermissive.option(path).property.get()) == set(default_props) else: + raises(PropertiesOptionError, "api.option(path, 0).property.get()") assert set(api.forcepermissive.option(path, 0).property.get()) == set(default_props) assert set(api.forcepermissive.option(path, 1).property.get()) == set(default_props) else: @@ -588,7 +578,8 @@ def autocheck_owner_with_value(api, path, **kwargs): if not isslave: assert api.forcepermissive.option(path).owner.isdefault() is False else: - assert api.forcepermissive.option(path, 0).owner.isdefault() is False + assert api.forcepermissive.option(path, 0).owner.isdefault() is True + assert api.forcepermissive.option(path, 1).owner.isdefault() is False else: raises(PropertiesOptionError, "api.forcepermissive.option(path).owner.isdefault()") @@ -773,18 +764,15 @@ def check_all(api, path, multi, **kwargs): def make_api(options, multi): - def make_option(path): - option_infos = path.split('_') + def make_option(path, option_infos): + #FIXME option_type = 'str' option_properties = [] - for option_info in option_infos[1:]: - if option_info in OPTIONS_TYPE: - option_type = option_info - elif option_info in PROPERTIES: - option_properties.append(option_info) - else: - raise Exception('unknown {} in {}'.format(option_info, path)) - args = [option_infos[0], "{}'s option".format(option_infos[0])] + if option_infos is not None: + for prop in PROPERTIES: + if option_infos.get(prop, False) is True: + option_properties.append(prop) + args = [path, "{}'s option".format(path)] kwargs = {} if option_properties != []: kwargs['properties'] = tuple(option_properties) @@ -794,28 +782,26 @@ def make_api(options, multi): return tiramisu_option(*args, **kwargs) def make_optiondescriptions(path, collected): - infos = path.split('_') - name = infos[0] + infos = collected.get('properties', {}) properties = [] kwargs = {} optiondescription = OptionDescription - for info in infos[1:]: - if info in PROPERTIES: - properties.append(info) - elif info == 'master': - if not multi: - return - optiondescription = MasterSlaves - elif info == 'dyn': - optiondescription = DynOptionDescription - kwargs['callback'] = return_list - else: - raise Exception('unknown {} in {}'.format(info, path)) + + for prop in PROPERTIES: + if infos.get(prop, False) is True: + properties.append(prop) + if infos.get('master', False) is True: + if not multi: + return + optiondescription = MasterSlaves + if infos.get('dyn', False) is True: + optiondescription = DynOptionDescription + kwargs['callback'] = return_list options = [] if 'options' in collected: options.extend(collected['options']) for key, values in collected.items(): - if key == 'options': + if key in ['options', 'properties']: continue option = make_optiondescriptions(key, values) if option is None: @@ -823,19 +809,20 @@ def make_api(options, multi): options.append(option) if properties != []: kwargs['properties'] = tuple(properties) - return optiondescription(name, "{}'s optiondescription".format(name), options, **kwargs) + return optiondescription(path, "{}'s optiondescription".format(path), options, **kwargs) collect_options = {} - for option in options: + for path, option in options.items(): if option is None: continue local_collect_options = collect_options - for optiondescription in option.split('.')[:-1]: - local_collect_options.setdefault(optiondescription, {}) + for optiondescription in path.split('.')[:-1]: + local_collect_options.setdefault(optiondescription, {'properties': {}}) local_collect_options = local_collect_options[optiondescription] - path = '.'.join(option.split('.')[:-1]) - option_name = option.split('.')[-1] - local_collect_options.setdefault("options", []).append(make_option(option_name)) + local_collect_options['properties'].update(option.get(optiondescription, {})) + option_name = path.split('.')[-1] + path = '.'.join(path.split('.')[:-1]) + local_collect_options.setdefault('options', []).append(make_option(option_name, option.get(option_name))) rootod = make_optiondescriptions('root', collect_options) if rootod is None: @@ -846,39 +833,45 @@ def make_api(options, multi): DICT_PATHS = [ #test a config without optiondescription - OrderedDict([('first', 'first'), - ('second', 'second_disabled'), - ('third', 'third_hidden')]), + OrderedDict([('first', {}), + ('second', {'second': {'disabled': True}}), + ('third', {'third': {'hidden': True}})]), #test a config with an optiondescription - OrderedDict([('subod.first', 'subod.first'), - ('subod.second', 'subod.second_disabled'), - ('subod.third', 'subod.third_hidden')]), + OrderedDict([('subod.first', {}), + ('subod.second', {'second': {'disabled': True}}), + ('subod.third', {'third': {'hidden': True}})]), #test a config with two optiondescription - OrderedDict([('subod.subsubod.first', 'subod.subsubod.first'), - ('subod.subsubod.second', 'subod.subsubod.second_disabled'), - ('subod.subsubod.third', 'subod.subsubod.third_hidden')]), + OrderedDict([('subod.subsubod.first', {}), + ('subod.subsubod.second', {'second': {'disabled': True}}), + ('subod.subsubod.third', {'third': {'hidden': True}})]), #test a config with mix of different optiondescription - OrderedDict([('first', 'first'), - ('subod.second', 'subod.second_disabled'), - ('subod.subsubod.third', 'subod.subsubod.third_hidden')]), + OrderedDict([('first', {}), + ('subod.second', {'second': {'disabled': True}}), + ('subod.subsubod.third', {'third': {'hidden': True}})]), #test a config with masterslaves - OrderedDict([('first.first', 'first_master.first'), - ('first.second', 'first_master.second_disabled'), - ('first.third', 'first_master.third_hidden')]), + OrderedDict([('odmaster.first', {'odmaster': {'master': True}}), + ('odmaster.second', {'second': {'disabled': True}}), + ('odmaster.third', {'third': {'hidden': True}})]), ##test a config with dynoption - OrderedDict([('subodval1.firstval1', 'subod_dyn.first'), - ('subodval1.secondval1', 'subod_dyn.second_disabled'), - ('subodval1.thirdval1', 'subod_dyn.third_hidden'), + OrderedDict([('subod.first', {'subod': {'dyn': True}}), + ('subod.second', {'second': {'disabled': True}}), + ('subod.third', {'third': {'hidden': True}}), + ('subodval1.firstval1', None), + ('subodval1.secondval1', None), + ('subodval1.thirdval1', None), ('subodval2.firstval2', None), ('subodval2.secondval2', None), ('subodval2.thirdval2', None)]), #test a config with dynoption subdir - OrderedDict([('subod.subodval1.firstval1', 'subod.subod_dyn.first'), - ('subod.subodval1.secondval1', 'subod.subod_dyn.second_disabled'), - ('subod.subodval1.thirdval1', 'subod.subod_dyn.third_hidden'), - ('subod.subodval2.firstval2', None), - ('subod.subodval2.secondval2', None), - ('subod.subodval2.thirdval2', None)]) + OrderedDict([('subod.subsubod.first', {'subsubod': {'dyn': True}}), + ('subod.subsubod.second', {'second': {'disabled': True}}), + ('subod.subsubod.third', {'third': {'hidden': True}}), + ('subod.subsubodval1.firstval1', None), + ('subod.subsubodval1.secondval1', None), + ('subod.subsubodval1.thirdval1', None), + ('subod.subsubodval2.firstval2', None), + ('subod.subsubodval2.secondval2', None), + ('subod.subsubodval2.thirdval2', None)]) ] @@ -892,31 +885,35 @@ def paths(request): def test_options(paths): lpaths = list(paths.keys()) for multi in (False, True): - api = make_api(paths.values(), multi) + api = make_api(paths, multi) if api is None: continue - check_all(api, lpaths[0], multi) - check_all(api, lpaths[1], multi, propertyerror=True, extra_properties=['disabled']) - check_all(api, lpaths[2], multi, permissive=True, extra_properties=['hidden']) - if len(lpaths) == 6: + if len(lpaths) == 9: check_all(api, lpaths[3], multi) check_all(api, lpaths[4], multi, propertyerror=True, extra_properties=['disabled']) check_all(api, lpaths[5], multi, permissive=True, extra_properties=['hidden']) - ## - #print('') - #print(api.help) + check_all(api, lpaths[6], multi) + check_all(api, lpaths[7], multi, propertyerror=True, extra_properties=['disabled']) + check_all(api, lpaths[8], multi, permissive=True, extra_properties=['hidden']) + else: + check_all(api, lpaths[0], multi) + check_all(api, lpaths[1], multi, propertyerror=True, extra_properties=['disabled']) + check_all(api, lpaths[2], multi, permissive=True, extra_properties=['hidden']) DICT_PATHS2 = [ - OrderedDict([('subod.subsubod.first', 'subod.subsubod_hidden.first'), - ('subod.subsubod.second', 'subod.subsubod_hidden.second'), - ('subod.subsubod.third', 'subod.subsubod_hidden.third_hidden')]), - OrderedDict([('subod.subodval1.firstval1', 'subod.subod_dyn_hidden.first'), - ('subod.subodval1.secondval1', 'subod.subod_dyn_hidden.second'), - ('subod.subodval1.thirdval1', 'subod.subod_dyn_hidden.third_hidden'), - ('subod.subodval2.firstval2', None), - ('subod.subodval2.secondval2', None), - ('subod.subodval2.thirdval2', None)]) + OrderedDict([('subod.subsubod.first', {'subsubod': {'hidden': True}}), + ('subod.subsubod.second', {}), + ('subod.subsubod.third', {})]), + OrderedDict([('subod.subsubod.first', {'subsubod': {'dyn': True, 'hidden': True}}), + ('subod.subsubod.second', {}), + ('subod.subsubod.third', {}), + ('subod.subsubodval1.firstval1', None), + ('subod.subsubodval1.secondval1', None), + ('subod.subsubodval1.thirdval1', None), + ('subod.subsubodval2.firstval2', None), + ('subod.subsubodval2.secondval2', None), + ('subod.subsubodval2.thirdval2', None)]) ] @@ -932,13 +929,17 @@ def test_tree_od_permissive(paths2): """ lpaths = list(paths2.keys()) for multi in (False, True): - api = make_api(paths2.values(), multi) + api = make_api(paths2, multi) if api is None: continue - check_all(api, lpaths[0], multi, permissive=True) - check_all(api, lpaths[1], multi, permissive=True) - check_all(api, lpaths[2], multi, permissive=True, extra_properties=['hidden']) - if len(lpaths) == 6: + if len(lpaths) == 9: check_all(api, lpaths[3], multi, permissive=True) check_all(api, lpaths[4], multi, permissive=True) - check_all(api, lpaths[5], multi, permissive=True, extra_properties=['hidden']) + check_all(api, lpaths[5], multi, permissive=True) + check_all(api, lpaths[6], multi, permissive=True) + check_all(api, lpaths[7], multi, permissive=True) + check_all(api, lpaths[8], multi, permissive=True) + else: + check_all(api, lpaths[0], multi, permissive=True) + check_all(api, lpaths[1], multi, permissive=True) + check_all(api, lpaths[2], multi, permissive=True) diff --git a/test/test_parsing_group.py b/test/test_parsing_group.py index 1ae909a..6ba0826 100644 --- a/test/test_parsing_group.py +++ b/test/test_parsing_group.py @@ -285,12 +285,6 @@ def test_values_with_master_remove(): assert cfg.ip_admin_eth0.netmask_admin_eth0 == ['255.255.255.128'] -def test_master_not_valid_name(): - ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True) - netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True) - raises(ValueError, "MasterSlaves('interface1', '', [ip_admin_eth0, netmask_admin_eth0])") - - def test_sub_group_in_master_group(): ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True) netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True) diff --git a/tiramisu/api.py b/tiramisu/api.py index c3e31c6..1781eb9 100644 --- a/tiramisu/api.py +++ b/tiramisu/api.py @@ -35,6 +35,7 @@ class CommonTiramisu(object): path, index, config, + setting_properties, force_permissive, force_unrestraint): self.opt = opt @@ -43,6 +44,7 @@ class CommonTiramisu(object): if self.slave_need_index: self._test_slave_index() self.config = config + self.setting_properties = setting_properties self.force_permissive = force_permissive self.force_unrestraint = force_unrestraint if not self.allow_unrestraint: @@ -81,11 +83,19 @@ class TiramisuOptionOption(CommonTiramisu): allow_unrestraint = True slave_need_index = False - def __init__(self, opt, path, index, config, force_permissive, force_unrestraint): + def __init__(self, + opt, + path, + index, + config, + setting_properties, + force_permissive, + force_unrestraint): super(TiramisuOptionOption, self).__init__(opt, path, index, config, + setting_properties, force_permissive, force_unrestraint) if config: @@ -117,11 +127,19 @@ class TiramisuOptionOption(CommonTiramisu): class TiramisuOptionOwner(CommonTiramisu): """manager option's owner""" - def __init__(self, opt, path, index, config, force_permissive, force_unrestraint): + def __init__(self, + opt, + path, + index, + config, + setting_properties, + force_permissive, + force_unrestraint): super(TiramisuOptionOwner, self).__init__(opt, path, index, config, + setting_properties, force_permissive, force_unrestraint) if config: @@ -135,9 +153,8 @@ class TiramisuOptionOwner(CommonTiramisu): def isdefault(self): """is option has defaut value""" - #FIXME isdefault for slave should have index! - #FIXME should not be here, just for check property return self.values.is_default_owner(self.opt, + index=self.index, force_permissive=self.force_permissive) def set(self, owner): @@ -158,11 +175,19 @@ class TiramisuOptionProperty(CommonTiramisu): #allow_unrestraint = True slave_need_index = False - def __init__(self, opt, path, index, config, force_permissive, force_unrestraint): + def __init__(self, + opt, + path, + index, + config, + setting_properties, + force_permissive, + force_unrestraint): super(TiramisuOptionProperty, self).__init__(opt, path, index, config, + setting_properties, force_permissive, force_unrestraint) if config: @@ -170,7 +195,10 @@ class TiramisuOptionProperty(CommonTiramisu): def get(self): self._test_slave_index() - return self.settings.getproperties(self.opt, self.path, index=self.index, obj=False) + return self.settings.getproperties(self.opt, + self.path, + index=self.index, + obj=False) def set(self, properties): """set properties for a specified option""" @@ -189,11 +217,19 @@ class TiramisuOptionPermissive(CommonTiramisu): allow_unrestraint = True slave_need_index = False - def __init__(self, opt, path, index, config, force_permissive, force_unrestraint): + def __init__(self, + opt, + path, + index, + config, + setting_properties, + force_permissive, + force_unrestraint): super(TiramisuOptionPermissive, self).__init__(opt, path, index, config, + setting_properties, force_permissive, force_unrestraint) if config: @@ -201,8 +237,7 @@ class TiramisuOptionPermissive(CommonTiramisu): def get(self): """get permissive value for a specified path""" - setting_properties = self.settings.getproperties(None, None, obj=False) - return self.settings.getpermissive(setting_properties, self.path) + return self.settings.getpermissive(self.setting_properties, self.path) def set(self, permissive): self.settings.setpermissive(permissive, opt=self.opt, path=self.path) @@ -217,25 +252,28 @@ class TiramisuOptionPermissive(CommonTiramisu): class TiramisuOptionValue(CommonTiramisu): """manager option's value""" - def __init__(self, opt, path, index, config, force_permissive, force_unrestraint): + def __init__(self, + opt, + path, + index, + config, + setting_properties, + force_permissive, + force_unrestraint): + super(TiramisuOptionValue, self).__init__(opt, path, index, config, + setting_properties, force_permissive, force_unrestraint) - def append(self, value=undefined): - if not self.opt.impl_is_master_slaves('master'): - raise APIError('append is only allowed for a master') - multi = self.config.getattr(self.path, - force_permissive=self.force_permissive) - multi.append(value) - self.set(multi) - def get(self): + settings = self.config.cfgimpl_get_settings() value = self.config.getattr(self.path, index=self.index, + setting_properties=self.setting_properties, force_permissive=self.force_permissive) if isinstance(value, Multi): value = list(value) @@ -247,45 +285,53 @@ class TiramisuOptionValue(CommonTiramisu): if isinstance(value, list): while undefined in value: idx = value.index(undefined) - value[idx] = values._getdefaultvalue(self.opt, - self.path, - True, - idx, - undefined, - True) + value[idx] = values.getdefaultvalue(self.opt, + self.path, + idx) else: if value == undefined: - value = values._getdefaultvalue(self.opt, - self.path, - True, - self.index, - undefined, - True) + value = values.getdefaultvalue(self.opt, + self.path, + self.index) self.config.setattr(self.path, value, index=self.index, force_permissive=self.force_permissive) + def pop(self, index): + """pop value for a specified master values + """ + self.config.delattr(self.path, + index=index, + setting_properties=self.setting_properties, + force_permissive=self.force_permissive) + def reset(self): """reset value for a value""" - if self.index is None: - self.config.cfgimpl_get_values().reset(self.opt, - path=self.path, - force_permissive=self.force_permissive) - else: - #FIXME ... _p_ ... - self.config.cfgimpl_get_values()._p_.resetvalue_index(self.path, self.index) + self.config.delattr(self.path, + index=self.index, + setting_properties=self.setting_properties, + force_permissive=self.force_permissive) class TiramisuOption(object): icon = '\u2937' tmpl_help = ' {} {}: {}' - def __init__(self, opt, path, index, config, force_permissive=False, force_unrestraint=False): + def __init__(self, + opt, + path, + index, + config, + setting_properties, + force_permissive, + force_unrestraint): + self.opt = opt self.path = path self.index = index self.config = config + self.setting_properties = setting_properties self.force_permissive = force_permissive self.force_unrestraint = force_unrestraint self.registers = {} @@ -310,6 +356,7 @@ class TiramisuOption(object): self.path, self.index, self.config, + self.setting_properties, self.force_permissive, self.force_unrestraint) elif subfunc == 'help': @@ -322,18 +369,25 @@ class TiramisuAPI(object): icon = '\u2937' tmpl_help = ' {} {}: {}' - def __init__(self, config, force_permissive=False, force_unrestraint=False): + def __init__(self, + config, + force_permissive=False, + force_unrestraint=False): self.config = config self.force_permissive = force_permissive self.force_unrestraint = force_unrestraint + settings = self.config.cfgimpl_get_settings() #FIXME ? self.config.read_write() - self.config.cfgimpl_get_settings().setpermissive(('hidden',)) + settings.setpermissive(('hidden',)) #/FIXME ? def option(self, path, index=None): validate = not self.force_unrestraint + settings = self.config.cfgimpl_get_settings() + setting_properties = settings.get_global_properties() opt = self.config.unwrap_from_path(path, + setting_properties=setting_properties, validate=validate, validate_properties=validate, force_permissive=self.force_permissive, @@ -344,14 +398,19 @@ class TiramisuAPI(object): path, index, self.config, - force_permissive=self.force_permissive, - force_unrestraint=self.force_unrestraint) + setting_properties, + self.force_permissive, + self.force_unrestraint) def __getattr__(self, subfunc): if subfunc == 'forcepermissive': - return TiramisuAPI(self.config, force_permissive=True, force_unrestraint=self.force_unrestraint) + return TiramisuAPI(self.config, + force_permissive=True, + force_unrestraint=self.force_unrestraint) elif subfunc == 'unrestraint': - return TiramisuAPI(self.config, force_permissive=self.force_permissive, force_unrestraint=True) + return TiramisuAPI(self.config, + force_permissive=self.force_permissive, + force_unrestraint=True) elif subfunc == 'help': return self._help() else: diff --git a/tiramisu/config.py b/tiramisu/config.py index 19dda72..9ff65eb 100644 --- a/tiramisu/config.py +++ b/tiramisu/config.py @@ -146,6 +146,7 @@ class SubConfig(object): def cfgimpl_get_home_by_path(self, path, force_permissive=False, returns_raise=False, _setting_properties=undefined, + setting_properties=undefined, validate_properties=True): """:returns: tuple (config, name)""" path = path.split('.') @@ -154,6 +155,7 @@ class SubConfig(object): force_permissive=force_permissive, returns_raise=returns_raise, validate_properties=validate_properties, + setting_properties=setting_properties, _setting_properties=_setting_properties) if isinstance(self, Exception): return self, None @@ -314,9 +316,59 @@ class SubConfig(object): return ret def __delattr__(self, name): + self.delattr(name) + + def delattr(self, + name, + index=None, + force_permissive=False, + setting_properties=undefined, + validate=True, + not_raises=False): context = self._cfgimpl_get_context() - child = self.cfgimpl_get_description().__getattr__(name, context) - self.cfgimpl_get_values().__delitem__(child) + if setting_properties is undefined: + setting_properties = context.cfgimpl_get_settings()._getproperties(read_write=True) + if '.' in name: # pragma: optional cover + self, name = self.cfgimpl_get_home_by_path(name, + force_permissive=force_permissive, + setting_properties=setting_properties) + child = self.cfgimpl_get_description().__getattr__(name, + context=context) + if isinstance(child, (OptionDescription, SynDynOptionDescription)): + raise TypeError(_("can't delete an OptionDescription")) # pragma: optional cover + elif child._is_symlinkoption() and \ + not isinstance(child, DynSymLinkOption): # pragma: no dynoptiondescription cover + raise TypeError(_("can't delete a SymlinkOption")) + else: + subpath = self._get_subpath(name) + values = self.cfgimpl_get_values() + if index is not None: + if child.impl_is_master_slaves('master'): + ret = values.reset_master(self, + child, + subpath, + index, + force_permissive, + setting_properties) + elif child.impl_is_master_slaves('slave'): + ret = values.reset_slave(child, + subpath, + index, + setting_properties, + force_permissive=force_permissive, + validate=validate) + else: + raise ValueError(_("can delete value with index only with a master or a slave")) + else: + ret = values.reset(child, + subpath, + _setting_properties=setting_properties, + force_permissive=force_permissive, + validate=validate) + if ret: + if not_raises: + return ret + raise ret def __getattr__(self, name): return self.getattr(name) @@ -333,7 +385,7 @@ class SubConfig(object): subpath = self._impl_path + '.' + name return subpath - def getattr(self, name, force_permissive=False, validate=True, + def getattr(self, name, force_permissive=False, validate=True, setting_properties=undefined, _setting_properties=undefined, _self_properties=undefined, index=None, returns_raise=False, returns_option=False, validate_properties=True): @@ -347,7 +399,10 @@ class SubConfig(object): # for instance getattr(self, "creole.general.family.adresse_ip_eth0") context = self._cfgimpl_get_context() if _setting_properties is undefined: - _setting_properties = context.cfgimpl_get_settings()._getproperties(read_write=True) + if setting_properties is not undefined: + _setting_properties = setting_properties + else: + _setting_properties = context.cfgimpl_get_settings()._getproperties(read_write=True) if '.' in name: homeconfig, name = self.cfgimpl_get_home_by_path( name, force_permissive=force_permissive, @@ -691,27 +746,30 @@ class _CommonConfig(SubConfig): def unwrap_from_path(self, path, force_permissive=False, index=None, validate_properties=True, validate=True, - _setting_properties=undefined): + _setting_properties=undefined, setting_properties=undefined): """convenience method to extract and Option() object from the Config() and it is **fast**: finds the option directly in the appropriate namespace :returns: Option() """ - if _setting_properties is undefined: - context = self._cfgimpl_get_context() - _setting_properties = context.cfgimpl_get_settings()._getproperties(read_write=True) + if setting_properties is undefined: + if _setting_properties is not undefined: + setting_properties = _setting_properties + else: + context = self._cfgimpl_get_context() + setting_properties = context.cfgimpl_get_settings()._getproperties(read_write=True) if '.' in path: self, path = self.cfgimpl_get_home_by_path(path, validate_properties=validate_properties, force_permissive=force_permissive, - _setting_properties=_setting_properties) + _setting_properties=setting_properties) return self.getattr(path, validate_properties=validate_properties, validate=validate, force_permissive=force_permissive, index=index, - _setting_properties=_setting_properties, + _setting_properties=setting_properties, returns_option=True) def cfgimpl_get_path(self, dyn=True): @@ -928,6 +986,7 @@ class GroupConfig(_CommonConfig): def getattr(self, name, force_permissive=False, validate=True, _setting_properties=undefined, _self_properties=undefined, index=None, + setting_properties=undefined, returns_raise=False, returns_option=False, validate_properties=True): for child in self._impl_children: @@ -938,6 +997,7 @@ class GroupConfig(_CommonConfig): _self_properties=_self_properties, index=index, _setting_properties=_setting_properties, + setting_properties=setting_properties, returns_raise=returns_raise, returns_option=False, validate_properties=validate_properties) diff --git a/tiramisu/option/optiondescription.py b/tiramisu/option/optiondescription.py index 1aede43..56e9de2 100644 --- a/tiramisu/option/optiondescription.py +++ b/tiramisu/option/optiondescription.py @@ -572,10 +572,6 @@ class MasterSlaves(OptionDescription): self._group_type = groups.master slaves = [] master = children[0] - if master.impl_getname() != name: - raise ValueError(_('master group with wrong' - ' master name for {0}' - ).format(name)) for child in children[1:]: if child.impl_getdefault() != []: raise ValueError(_("not allowed default value for option {0} " diff --git a/tiramisu/setting.py b/tiramisu/setting.py index fdab002..fa2a11a 100644 --- a/tiramisu/setting.py +++ b/tiramisu/setting.py @@ -377,6 +377,9 @@ class Settings(object): self._p_.delproperties(_path) self._getcontext().cfgimpl_reset_cache(opt=opt, path=_path, only=('settings', 'values')) + def get_global_properties(self): + return self._getproperties() + def _getproperties(self, opt=None, path=None, setting_properties=undefined, read_write=True, apply_requires=True, index=None): diff --git a/tiramisu/storage/util.py b/tiramisu/storage/util.py index 59a941c..5cf1fc7 100644 --- a/tiramisu/storage/util.py +++ b/tiramisu/storage/util.py @@ -15,6 +15,12 @@ # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # ____________________________________________________________ +FIXME = 0 +def POUET(obj): + return(obj.__class__.__name__.lower()) + +DEBUG = False +#DEBUG = True class Cache(object): @@ -29,17 +35,41 @@ class Cache(object): """add val in cache for a specified path if slave, add index """ + if DEBUG: + global FIXME + FIXME += 1 + print('ca set cache', path, val, POUET(self), FIXME) + #if path is not None and (path.startswith('od.st.') or path.startswith('od.dod.')): + # raise Exception('mais ... mais ... mais') + #if FIXME == 111: + # raise Exception('rah') self._cache.setdefault(path, {})[index] = (val, time) def getcache(self, path, exp, index): value, created = self._cache[path][index] if created is None or exp <= created: + if DEBUG: + global FIXME + FIXME += 1 + print('ca trouve dans le cache', path, value, POUET(self), FIXME) + #if path is not None and (path.startswith('od.st.') or path.startswith('od.dod.')): + # raise Exception('mais ... mais ... mais') + #if FIXME == 45: + # raise Exception('rah') return True, value return False, None # pragma: no cover def delcache(self, path): """remove cache for a specified path """ + if DEBUG: + global FIXME + FIXME += 1 + print('ca del cache', path, POUET(self), FIXME) + #if path is not None and (path.startswith('od.st.') or path.startswith('od.dod.')): + # raise Exception('mais ... mais ... mais') + #if FIXME == 23: + # raise Exception('rah') if path in self._cache: del self._cache[path] @@ -48,6 +78,8 @@ class Cache(object): :param path: the path's option """ + if DEBUG: + print('ca cherche dans le cache', path, POUET(self)) return path in self._cache and index in self._cache[path] def reset_expired_cache(self, exp): @@ -63,6 +95,8 @@ class Cache(object): def reset_all_cache(self): "empty the cache" + if DEBUG: + print('bzzzzzzzzzzzz delete tout le cache', POUET(self)) self._cache.clear() def get_cached(self): diff --git a/tiramisu/value.py b/tiramisu/value.py index efdbed9..ad3067b 100644 --- a/tiramisu/value.py +++ b/tiramisu/value.py @@ -211,6 +211,63 @@ class Values(object): self._p_.resetvalue(path, session, _commit) context.cfgimpl_reset_cache(opt=opt, path=path, only=('values', 'properties')) + def reset_slave(self, + opt, + path, + index, + setting_properties, + validate=True, + force_permissive=False): + + context = self._getcontext() + if validate and 'validator' in setting_properties: + session = context.cfgimpl_get_values()._p_.getsession() + fake_context = context._gen_fake_values(session) + fake_value = fake_context.cfgimpl_get_values() + fake_value.reset_slave(opt, + path, + index, + setting_properties, + validate=False) + ret = fake_value._get_cached_value(opt, + path, + index=index, + setting_properties=setting_properties, + check_frozen=True, + force_permissive=force_permissive) + if isinstance(ret, Exception): + raise ret + self._p_.resetvalue_index(path, index) + + def reset_master(self, + subconfig, + opt, + path, + index, + force_permissive, + setting_properties): + + current_value = self._get_cached_value(opt, + path, + setting_properties=setting_properties, + check_frozen=True, + force_permissive=force_permissive) + current_value.pop(index) + ret = self.setitem(opt, + current_value, + path, + force_permissive=force_permissive, + not_raises=True, + index=None, + setting_properties=setting_properties, + _commit=True) + if ret: + return ret + subconfig.cfgimpl_get_description().pop(opt, + path, + self, + index) + def _isempty(self, opt, value, force_allow_empty_list=False, index=None): "convenience method to know if an option is empty" if value is undefined: