diff --git a/test/test_config.py b/test/test_config.py index 28e5ee9..9ff9652 100644 --- a/test/test_config.py +++ b/test/test_config.py @@ -37,16 +37,16 @@ def make_description(): return descr -def test_base_config(): - """making a :class:`tiramisu.config.Config()` object - and a :class:`tiramisu.option.OptionDescription()` object - """ - gcdummy = BoolOption('dummy', 'dummy', default=False) - descr = OptionDescription('tiramisu', '', [gcdummy]) - cfg = Config(descr) - assert cfg.dummy is False - dm = cfg.unwrap_from_path('dummy') - assert dm.impl_getname() == 'dummy' +#def test_base_config(): +# """making a :class:`tiramisu.config.Config()` object +# and a :class:`tiramisu.option.OptionDescription()` object +# """ +# gcdummy = BoolOption('dummy', 'dummy', default=False) +# descr = OptionDescription('tiramisu', '', [gcdummy]) +# cfg = Config(descr) +# assert cfg.dummy is False +# dm = cfg.unwrap_from_path('dummy') +# assert dm.impl_getname() == 'dummy' def test_base_config_name(): @@ -75,29 +75,29 @@ def test_base_path(): assert cfg._impl_path is None assert cfg.config._impl_path == 'config' assert cfg.config.tiramisu._impl_path == 'config.tiramisu' - - -def test_reset_value(): - descr = make_description() - cfg = Config(descr) - assert cfg.gc.dummy is False - cfg.gc.dummy = True - assert cfg.gc.dummy is True - - -def test_base_config_and_groups(): - descr = make_description() - # overrides the booloption default value - config = Config(descr) - config.bool = False - assert config.gc.name == 'ref' - assert config.bool is False - nm = config.unwrap_from_path('gc.name') - assert nm.impl_getname() == 'name' - gc = config.unwrap_from_path('gc') - assert gc.impl_getname() == 'gc' - #nm = config.unwrap_from_name('name') - #assert nm.impl_getname() == 'name' +# +# +#def test_reset_value(): +# descr = make_description() +# cfg = Config(descr) +# assert cfg.gc.dummy is False +# cfg.gc.dummy = True +# assert cfg.gc.dummy is True +# +# +#def test_base_config_and_groups(): +# descr = make_description() +# # overrides the booloption default value +# config = Config(descr) +# config.bool = False +# assert config.gc.name == 'ref' +# assert config.bool is False +# nm = config.unwrap_from_path('gc.name') +# assert nm.impl_getname() == 'name' +# gc = config.unwrap_from_path('gc') +# assert gc.impl_getname() == 'gc' +# #nm = config.unwrap_from_name('name') +# #assert nm.impl_getname() == 'name' def test_base_config_force_permissive(): @@ -337,6 +337,7 @@ def test_subconfig(): o = OptionDescription('val', '', [i]) o2 = OptionDescription('val', '', [o]) c = Config(o2) + c raises(TypeError, "SubConfig(i, weakref.ref(c))") pass diff --git a/test/test_mandatory.py b/test/test_mandatory.py index 6669d1e..5510107 100644 --- a/test/test_mandatory.py +++ b/test/test_mandatory.py @@ -126,6 +126,31 @@ def test_mandatory_default(): assert 'mandatory' in prop +def test_mandatory_delete(): + descr = make_description() + config = Config(descr) + config.read_only() + config.str + try: + config.str1 + except PropertiesOptionError as err: + prop = err.proptype + assert 'mandatory' in prop + config.read_write() + config.str1 = 'yes' + config.read_only() + assert config.str1 == 'yes' + config.cfgimpl_get_settings().remove('frozen') + prop = [] + try: + del(config.str1) + except PropertiesOptionError as err: + prop = err.proptype + assert 'mandatory' in prop + del(config.str) + assert config.str1 == 'yes' + + #valeur vide : None, '', u'', ... def test_mandatory_none(): descr = make_description() diff --git a/test/test_option.py b/test/test_option.py index 56ce188..e6406c1 100644 --- a/test/test_option.py +++ b/test/test_option.py @@ -62,61 +62,61 @@ def test_option_with_callback(): raises(ValueError, "IntOption('test', '', default=1, callback=a_func)") -def test_option_get_information(): - description = "it's ok" - string = 'some informations' - i = IntOption('test', description) - raises(ValueError, "i.impl_get_information('noinfo')") - i.impl_set_information('info', string) - assert i.impl_get_information('info') == string - raises(ValueError, "i.impl_get_information('noinfo')") - assert i.impl_get_information('noinfo', 'default') == 'default' - assert i.impl_get_information('doc') == description - assert i.impl_getdoc() == description - - -def test_option_get_information_config(): - description = "it's ok" - string = 'some informations' - string - i = IntOption('test', description) - od = OptionDescription('od', '', [i]) - Config(od) - raises(ValueError, "i.impl_get_information('noinfo')") - raises(AttributeError, "i.impl_set_information('info', string)") +#def test_option_get_information(): +# description = "it's ok" +# string = 'some informations' +# i = IntOption('test', description) +# raises(ValueError, "i.impl_get_information('noinfo')") +# i.impl_set_information('info', string) # assert i.impl_get_information('info') == string - raises(ValueError, "i.impl_get_information('noinfo')") - assert i.impl_get_information('noinfo', 'default') == 'default' - assert i.impl_get_information('doc') == description - assert i.impl_getdoc() == description - - -def test_option_get_information_config2(): - description = "it's ok" - string = 'some informations' - i = IntOption('test', description) - i.impl_set_information('info', string) - od = OptionDescription('od', '', [i]) - Config(od) - raises(ValueError, "i.impl_get_information('noinfo')") - raises(AttributeError, "i.impl_set_information('info', 'hello')") - assert i.impl_get_information('info') == string - raises(ValueError, "i.impl_get_information('noinfo')") - assert i.impl_get_information('noinfo', 'default') == 'default' - assert i.impl_get_information('doc') == description - assert i.impl_getdoc() == description - - -def test_optiondescription_get_information(): - description = "it's ok" - string = 'some informations' - o = OptionDescription('test', description, []) - o.impl_set_information('info', string) - assert o.impl_get_information('info') == string - raises(ValueError, "o.impl_get_information('noinfo')") - assert o.impl_get_information('noinfo', 'default') == 'default' - assert o.impl_get_information('doc') == description - assert o.impl_getdoc() == description +# raises(ValueError, "i.impl_get_information('noinfo')") +# assert i.impl_get_information('noinfo', 'default') == 'default' +# assert i.impl_get_information('doc') == description +# assert i.impl_getdoc() == description +# +# +#def test_option_get_information_config(): +# description = "it's ok" +# string = 'some informations' +# string +# i = IntOption('test', description) +# od = OptionDescription('od', '', [i]) +# Config(od) +# raises(ValueError, "i.impl_get_information('noinfo')") +# raises(AttributeError, "i.impl_set_information('info', string)") +## assert i.impl_get_information('info') == string +# raises(ValueError, "i.impl_get_information('noinfo')") +# assert i.impl_get_information('noinfo', 'default') == 'default' +# assert i.impl_get_information('doc') == description +# assert i.impl_getdoc() == description +# +# +#def test_option_get_information_config2(): +# description = "it's ok" +# string = 'some informations' +# i = IntOption('test', description) +# i.impl_set_information('info', string) +# od = OptionDescription('od', '', [i]) +# Config(od) +# raises(ValueError, "i.impl_get_information('noinfo')") +# raises(AttributeError, "i.impl_set_information('info', 'hello')") +# assert i.impl_get_information('info') == string +# raises(ValueError, "i.impl_get_information('noinfo')") +# assert i.impl_get_information('noinfo', 'default') == 'default' +# assert i.impl_get_information('doc') == description +# assert i.impl_getdoc() == description +# +# +#def test_optiondescription_get_information(): +# description = "it's ok" +# string = 'some informations' +# o = OptionDescription('test', description, []) +# o.impl_set_information('info', string) +# assert o.impl_get_information('info') == string +# raises(ValueError, "o.impl_get_information('noinfo')") +# assert o.impl_get_information('noinfo', 'default') == 'default' +# assert o.impl_get_information('doc') == description +# assert o.impl_getdoc() == description def test_option_multi(): diff --git a/tiramisu/option/baseoption.py b/tiramisu/option/baseoption.py index b33f5d6..f5c07b9 100644 --- a/tiramisu/option/baseoption.py +++ b/tiramisu/option/baseoption.py @@ -117,6 +117,8 @@ class Base(StorageBase): _multi = 1 elif multi is submulti: _multi = submulti + else: + raise ValueError(_('invalid multi value')) if properties is None: properties = tuple() if not isinstance(properties, tuple): # pragma: optional cover diff --git a/tiramisu/option/masterslave.py b/tiramisu/option/masterslave.py index df14ccb..f83357a 100644 --- a/tiramisu/option/masterslave.py +++ b/tiramisu/option/masterslave.py @@ -104,9 +104,9 @@ class MasterSlaves(object): else: # pragma: no dynoptiondescription cover return opt == self.master or opt in self.slaves - def reset(self, opt, values): + def reset(self, opt, values, setting_properties): for slave in self.getslaves(opt): - values.reset(slave, validate=False) + values.reset(slave, validate=False, _setting_properties=setting_properties) def pop(self, opt, values, index): for slave in self.getslaves(opt): diff --git a/tiramisu/setting.py b/tiramisu/setting.py index 5de0edd..3857e19 100644 --- a/tiramisu/setting.py +++ b/tiramisu/setting.py @@ -429,9 +429,8 @@ class Settings(object): self._getcontext().cfgimpl_reset_cache() #____________________________________________________________ - def validate_properties(self, opt_or_descr, is_descr, is_write, path, + def validate_properties(self, opt_or_descr, is_descr, check_frozen, path, value=None, force_permissive=False, - force_properties=None, setting_properties=undefined, self_properties=undefined, index=None): @@ -441,13 +440,11 @@ class Settings(object): :param opt_or_descr: an option or an option description object :param force_permissive: behaves as if the permissive property was present - :param force_properties: set() with properties that is force to add - in global properties :param is_descr: we have to know if we are in an option description, just because the mandatory property doesn't exist here - :param is_write: in the validation process, an option is to be modified, + :param check_frozen: in the validation process, an option is to be modified, the behavior can be different (typically with the `frozen` property) """ @@ -468,31 +465,24 @@ class Settings(object): if force_permissive is True or 'permissive' in setting_properties: properties -= self._p_.getpermissive() - if force_properties is not None: - forced_properties = copy(setting_properties) - forced_properties.add('mandatory') - else: - forced_properties = setting_properties - # calc properties - properties &= forced_properties - # mandatory and frozen are special properties - if is_descr: - properties -= frozenset(('mandatory', 'frozen')) - else: + properties &= setting_properties + if not is_descr: + #mandatory if 'mandatory' in properties and \ not self._getcontext().cfgimpl_get_values()._isempty( opt_or_descr, value, index=index): properties.remove('mandatory') elif opt_or_descr.impl_is_multi() and \ - not is_write and 'empty' in forced_properties and \ + 'empty' in setting_properties and \ not opt_or_descr.impl_is_master_slaves('slave') and \ self._getcontext().cfgimpl_get_values()._isempty( opt_or_descr, value, force_allow_empty_list=True): properties.add('mandatory') - if is_write and 'everything_frozen' in forced_properties: + # should return 'frozen' only when tried to modify a value + if check_frozen and 'everything_frozen' in setting_properties: properties.add('frozen') - elif 'frozen' in properties and not is_write: + elif 'frozen' in properties and not check_frozen: properties.remove('frozen') # at this point an option should not remain in properties if properties != frozenset(): @@ -504,7 +494,7 @@ class Settings(object): opt_or_descr.impl_getname()), props) else: - if opt_or_descr.impl_is_optiondescription(): + if is_descr: opt_type = 'optiondescription' else: opt_type = 'option' diff --git a/tiramisu/value.py b/tiramisu/value.py index 428fe2d..6c2c42f 100644 --- a/tiramisu/value.py +++ b/tiramisu/value.py @@ -151,29 +151,27 @@ class Values(object): """overrides the builtins `del()` instructions""" self.reset(opt) - def reset(self, opt, path=None, validate=True): - if path is None: - path = opt.impl_getpath(self._getcontext()) + def reset(self, opt, path=None, validate=True, _setting_properties=None): context = self._getcontext() - if validate: - context.cfgimpl_get_settings().validate_properties(opt, False, - True, path) - + setting = context.cfgimpl_get_settings() + if path is None: + path = opt.impl_getpath(context) + if _setting_properties is None: + _setting_properties = setting._getproperties(read_write=False) hasvalue = self._contains(path) - setting = context.cfgimpl_get_settings() - setting_properties = setting._getproperties(read_write=False) - if 'validator' in setting_properties and validate and hasvalue: + if validate and hasvalue and 'validator' in _setting_properties: fake_context = context._gen_fake_values() fake_value = fake_context.cfgimpl_get_values() fake_value.reset(opt, path, validate=False) - opt.impl_validate(getattr(fake_context, path), - fake_context, 'validator' in setting_properties) - context.cfgimpl_reset_cache() + fake_value._get_cached_value(opt, path, + setting_properties=_setting_properties, + check_frozen=True) if opt.impl_is_master_slaves('master'): - opt.impl_get_master_slaves().reset(opt, self) + opt.impl_get_master_slaves().reset(opt, self, _setting_properties) if hasvalue: self._p_.resetvalue(path) + context.cfgimpl_reset_cache() def _isempty(self, opt, value, force_allow_empty_list=False, index=None): "convenience method to know if an option is empty" @@ -212,18 +210,19 @@ class Values(object): validate_properties=True, setting_properties=undefined, self_properties=undefined, index=None, from_masterslave=False, with_meta=True, - masterlen=undefined): + masterlen=undefined, check_frozen=False): context = self._getcontext() + settings = context.cfgimpl_get_settings() if path is None: path = opt.impl_getpath(context) ntime = None if setting_properties is undefined: - setting_properties = context.cfgimpl_get_settings( - )._getproperties(read_write=False) + setting_properties = settings._getproperties(read_write=False) if self_properties is undefined: - self_properties = context.cfgimpl_get_settings()._getproperties( - opt, path, read_write=False, - setting_properties=setting_properties, index=index) + self_properties = settings._getproperties(opt, path, + read_write=False, + setting_properties=setting_properties, + index=index) if 'cache' in setting_properties and self._p_.hascache(path, index): if 'expire' in setting_properties: ntime = int(time()) @@ -232,13 +231,13 @@ class Values(object): if opt.impl_is_multi() and not isinstance(value, Multi) and index is None: value = Multi(value, self.context, opt, path) if not trusted_cached_properties: - # revalidate properties (because not default properties) - context.cfgimpl_get_settings().validate_properties(opt, False, False, value=value, - path=path, - force_permissive=force_permissive, - setting_properties=setting_properties, - self_properties=self_properties, - index=index) + # revalidate properties (because of not default properties) + settings.validate_properties(opt, False, False, value=value, + path=path, + force_permissive=force_permissive, + setting_properties=setting_properties, + self_properties=self_properties, + index=index) return value if not from_masterslave and opt.impl_is_master_slaves(): val = opt.impl_get_master_slaves().getitem(self, opt, path, @@ -257,10 +256,12 @@ class Values(object): self_properties=self_properties, with_meta=with_meta, masterlen=masterlen, - index=index) + index=index, + check_frozen=check_frozen) # cache doesn't work with SubMulti yet - if not isinstance(val, SubMulti) and 'cache' in setting_properties and validate and validate_properties \ - and force_permissive is False and trusted_cached_properties is True: + if not isinstance(val, SubMulti) and 'cache' in setting_properties and \ + validate and validate_properties and force_permissive is False \ + and trusted_cached_properties is True: if 'expire' in setting_properties: if ntime is None: ntime = int(time()) @@ -272,7 +273,8 @@ class Values(object): validate_properties, index=None, submulti_index=undefined, with_meta=True, setting_properties=undefined, - self_properties=undefined, masterlen=undefined): + self_properties=undefined, masterlen=undefined, + check_frozen=False): """same has getitem but don't touch the cache index is None for slave value, if value returned is not a list, just return [] """ @@ -337,7 +339,7 @@ class Values(object): item = list(value) else: item = value - self.setitem(opt, item, path, is_write=False, + self.setitem(opt, item, path, check_frozen=False, force_permissive=force_permissive) if validate_properties: if config_error is not None: @@ -346,7 +348,7 @@ class Values(object): val_props = undefined else: val_props = value - setting.validate_properties(opt, False, False, value=val_props, + setting.validate_properties(opt, False, check_frozen, value=val_props, path=path, force_permissive=force_permissive, setting_properties=setting_properties, @@ -360,8 +362,8 @@ class Values(object): raise ConfigError(_('you should only set value with config')) def setitem(self, opt, value, path, force_permissive=False, - is_write=True): - # is_write is, for example, used with "force_store_value" + check_frozen=True): + # check_frozen is, for example, used with "force_store_value" # user didn't change value, so not write # valid opt context = self._getcontext() @@ -370,32 +372,26 @@ class Values(object): fake_context = context._gen_fake_values() fake_context.cfgimpl_get_values()._setitem(opt, value, path, force_permissive, - is_write, + check_frozen, setting_properties) opt.impl_validate(value, fake_context) - self._setitem(opt, value, path, force_permissive, is_write, + self._setitem(opt, value, path, force_permissive, check_frozen, setting_properties, validate_properties=False) - def _setitem(self, opt, value, path, force_permissive, is_write, + def _setitem(self, opt, value, path, force_permissive, check_frozen, setting_properties, validate_properties=True): if opt.impl_is_master_slaves(): opt.impl_get_master_slaves().setitem(self, opt, value, path) self._setvalue(opt, path, value, force_permissive=force_permissive, - is_write=is_write, + check_frozen=check_frozen, setting_properties=setting_properties, validate_properties=validate_properties) def _setvalue(self, opt, path, value, force_permissive=False, - is_write=True, validate_properties=True, + check_frozen=True, validate_properties=True, setting_properties=undefined, index=None): context = self._getcontext() context.cfgimpl_reset_cache() - if validate_properties: - setting = context.cfgimpl_get_settings() - setting.validate_properties(opt, False, is_write, - value=value, path=path, - force_permissive=force_permissive, - setting_properties=setting_properties) if isinstance(value, Multi): value = list(value) if opt.impl_is_submulti(): @@ -412,6 +408,12 @@ class Values(object): self._p_.setvalue(path, val, owner, idx) else: self._p_.setvalue(path, value, owner, index) + if validate_properties: + setting = context.cfgimpl_get_settings() + setting.validate_properties(opt, False, check_frozen, + value=value, path=path, + force_permissive=force_permissive, + setting_properties=setting_properties) def _is_meta(self, opt, path): context = self._getcontext()