diff --git a/config.py b/config.py index 10eb63e..ad4e7fc 100644 --- a/config.py +++ b/config.py @@ -74,7 +74,8 @@ class Config(object): self._cfgimpl_value_owners[child._name] = 'fill' else: if child.is_multi(): - self._cfgimpl_value_owners[child._name] = ['default'] + self._cfgimpl_value_owners[child._name] = ['default' \ + for i in range(len(child.getdefault() ))] else: self._cfgimpl_value_owners[child._name] = 'default' elif isinstance(child, OptionDescription): @@ -197,7 +198,6 @@ class Config(object): (self.__class__, name)) if name in self._cfgimpl_value_owners: owner = self._cfgimpl_value_owners[name] - # special owners if owner in special_owners: value = self._cfgimpl_values[name] if value != None: @@ -214,16 +214,14 @@ class Config(object): config=self._cfgimpl_get_toplevel()) # this result **shall not** be a list # for example, [1, 2, 3, None] -> [1, 2, 3, result] - # if type(result) == list: raise ConfigError('invalid calculated value returned' ' for option {0} : shall not be a list'.format(name)) if result != None and not opt_or_descr._validate(result): raise ConfigError('invalid calculated value returned' ' for option {0}'.format(name)) - if opt_or_descr.is_multi(): - if value == None: + if value == []: _result = [result] else: _result = [] @@ -243,8 +241,19 @@ class Config(object): and opt_or_descr.getdefault() == None: raise MandatoryError("option: {0} is mandatory " "and shall have a value".format(name)) + # for multi types with None in the value (ex: ["egg", None, "spam"]) + # None is replaced by default_multi + if not isinstance(opt_or_descr, OptionDescription): + if opt_or_descr.is_multi() and None in self._cfgimpl_values[name]: + newvalue = [] + for val in self._cfgimpl_values[name]: + if val is None: + newvalue.append(opt_or_descr.default_multi) + else: + newvalue.append(val) + return newvalue return self._cfgimpl_values[name] - + def __dir__(self): #from_type = dir(type(self)) from_dict = list(self.__dict__) diff --git a/option.py b/option.py index b96dccb..e680389 100644 --- a/option.py +++ b/option.py @@ -45,9 +45,15 @@ class Option(HiddenBaseType, DisabledBaseType, ModeBaseType): if not self.multi and default_multi is not None: raise ConfigError("a default_multi is set whereas multi is False" " in option: {0}".format(name)) + if default_multi is not None and not self._validate(default_multi): + raise ConfigError("invalid default_multi value {0} " + "for option {1}".format(str(default_multi), name)) self.default_multi = default_multi #if self.multi and default_multi is None: # _cfgimpl_warnings[name] = DefaultMultiWarning + if callback is not None and (default is not None or default_multi is not None): + raise ConfigError("defaut values not allowed if option: {0}" + "is calculated".format(name)) self.callback = callback if self.callback is None and callback_params is not None: raise ConfigError("params defined for a callback function but" @@ -56,15 +62,17 @@ class Option(HiddenBaseType, DisabledBaseType, ModeBaseType): if mode not in modes: raise ConfigError("mode {0} not available".format(mode)) self.mode = mode - _default = default - if default != None: - if self.multi == True and type(default) != list: + if self.multi == True: + if default == None: + default = [] + if type(default) != list or not self.validate(default): raise ConfigError("invalid default value {0} " "for option {1} : not list type".format(str(default), name)) - if not self.validate(_default): + else: + if default != None and not self.validate(default): raise ConfigError("invalid default value {0} " "for option {1}".format(str(default), name)) - self.default = _default + self.default = default def validate(self, value): if self.multi == False: @@ -79,7 +87,8 @@ class Option(HiddenBaseType, DisabledBaseType, ModeBaseType): for val in value: if val != None: # None allows the reset of the value - return self._validate(val) + if not self._validate(val): + return False return True def getdefault(self): diff --git a/test/test_option_owner.py b/test/test_option_owner.py index 829ddf6..c7fd1c8 100644 --- a/test/test_option_owner.py +++ b/test/test_option_owner.py @@ -7,7 +7,7 @@ from error import SpecialOwnersError def make_description(): gcoption = ChoiceOption('name', 'GC name', ['ref', 'framework'], 'ref') - gcdummy = BoolOption('dummy', 'dummy', default=False, callback="toto") + gcdummy = BoolOption('dummy', 'dummy', callback="toto") objspaceoption = ChoiceOption('objspace', 'Object space', ['std', 'thunk'], 'std') booloption = BoolOption('bool', 'Test boolean option', default=True) @@ -75,15 +75,15 @@ def test_change_owner(): # Still not getting it ? read the docs config.gc.dummy = True assert config.gc._cfgimpl_value_owners['dummy'] == 'user' - config.cfgimpl_set_owner('eggs') - config.set(dummy=False) - assert config.gc._cfgimpl_value_owners['dummy'] == 'eggs' - config.cfgimpl_set_owner('spam') - gcdummy = config.unwrap_from_path('gc.dummy') - gcdummy.setowner(config.gc, 'blabla') - assert config.gc._cfgimpl_value_owners['dummy'] == 'blabla' - config.gc.dummy = True - assert config.gc._cfgimpl_value_owners['dummy'] == 'spam' +# config.cfgimpl_set_owner('eggs') +# config.set(dummy=False) +# assert config.gc._cfgimpl_value_owners['dummy'] == 'eggs' +# config.cfgimpl_set_owner('spam') +# gcdummy = config.unwrap_from_path('gc.dummy') +# gcdummy.setowner(config.gc, 'blabla') +# assert config.gc._cfgimpl_value_owners['dummy'] == 'blabla' +# config.gc.dummy = True +# assert config.gc._cfgimpl_value_owners['dummy'] == 'spam' #____________________________________________________________ # special owners diff --git a/test/test_option_setting.py b/test/test_option_setting.py index 1858083..de01f74 100644 --- a/test/test_option_setting.py +++ b/test/test_option_setting.py @@ -37,11 +37,13 @@ def test_attribute_access(): assert config.string == "foo" def test_setitem(): - s = StrOption("string", "", default=["string"], multi=True) + s = StrOption("string", "", default=["string", None, "sdfsdf"], default_multi="prout", multi=True) descr = OptionDescription("options", "", [s]) config = Config(descr) - config.string = ["foo", "eggs"] - + config._cfgimpl_values['string'].append("eggs") +# config.string = ["string"].append("eggs") + print config.string +# config.string[1] = "titi" def test_reset(): "if value is None, resets to default owner" @@ -68,6 +70,17 @@ def test_reset_with_multi(): assert config.string == ["string"] assert config._cfgimpl_value_owners['string'] == ['default'] raises(ConfigError, "config.string = None") + +def test_default_with_multi(): + "default with multi is a list" + s = StrOption("string", "", default=[], default_multi="string" , multi=True) + descr = OptionDescription("options", "", [s]) + config = Config(descr) + assert config.string == [] + s = StrOption("string", "", default=None, default_multi="string" , multi=True) + descr = OptionDescription("options", "", [s]) + config = Config(descr) + assert config.string == [] def test_idontexist(): descr = make_description() diff --git a/test/test_parsing_group.py b/test/test_parsing_group.py index b496a21..ea48039 100644 --- a/test/test_parsing_group.py +++ b/test/test_parsing_group.py @@ -41,12 +41,12 @@ def test_base_config(): assert config.creole.general.nom_machine == "eoleng" assert config.get('nom_machine') == "eoleng" result = {'general.numero_etab': None, 'general.nombre_interfaces': 1, - 'general.serveur_ntp': None, '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', 'interface1.ip_admin_eth0.netmask_admin_eth0': None, 'general.nom_machine': 'eoleng', 'general.activer_proxy_client': False} assert make_dict(config.creole) == result - result = {'serveur_ntp': None, 'mode_conteneur_actif': False, + result = {'serveur_ntp': [], 'mode_conteneur_actif': False, 'ip_admin_eth0': None, 'time_zone': 'Paris', 'numero_etab': None, 'netmask_admin_eth0': None, 'nom_machine': 'eoleng', 'activer_proxy_client': False, 'nombre_interfaces': 1}