diff --git a/test/test_mandatory.py b/test/test_mandatory.py index 1010256..52456eb 100644 --- a/test/test_mandatory.py +++ b/test/test_mandatory.py @@ -12,7 +12,7 @@ def make_description(): stroption1 = StrOption('str1', 'Test string option', properties=('mandatory', )) stroption2 = UnicodeOption('unicode2', 'Test string option', - properties=('mandatory', )) + properties=('mandatory', )) stroption3 = StrOption('str3', 'Test string option', multi=True, properties=('mandatory', )) descr = OptionDescription('tiram', '', [stroption, stroption1, stroption2, stroption3]) diff --git a/test/test_option_consistency.py b/test/test_option_consistency.py index c8699a4..88f3626 100644 --- a/test/test_option_consistency.py +++ b/test/test_option_consistency.py @@ -162,7 +162,7 @@ def test_hidden_if_in(): assert not setting.has_property('hidden', stroption) cfg.int = 1 raises(PropertiesOptionError, "cfg.str") - raises(PropertiesOptionError, 'cfg.str= "uvw"') + raises(PropertiesOptionError, 'cfg.str="uvw"') assert setting.has_property('hidden', stroption) def test_hidden_if_in_with_group(): diff --git a/tiramisu/config.py b/tiramisu/config.py index 84e16e4..3402a0e 100644 --- a/tiramisu/config.py +++ b/tiramisu/config.py @@ -72,8 +72,8 @@ class SubConfig(object): return self._setattr(name, value) - def cfgimpl_reset_cache(self): - self.cfgimpl_get_context().cfgimpl_reset_cache() + def cfgimpl_reset_cache(self, only_expired=False, only=('values', 'settings')): + self.cfgimpl_get_context().cfgimpl_reset_cache(only_expired, only) def _setattr(self, name, value, force_permissive=False): if '.' in name: @@ -361,9 +361,11 @@ class Config(SubConfig): def _cfgimpl_build_all_paths(self): self._cfgimpl_descr.build_cache() - def cfgimpl_reset_cache(self, only_expired=False): - self.cfgimpl_get_values().reset_cache(only_expired=only_expired) - self.cfgimpl_get_settings().reset_cache(only_expired=only_expired) + def cfgimpl_reset_cache(self, only_expired=False, only=('values', 'settings')): + if 'values' in only: + self.cfgimpl_get_values().reset_cache(only_expired=only_expired) + if 'settings' in only: + self.cfgimpl_get_settings().reset_cache(only_expired=only_expired) def unwrap_from_path(self, path): """convenience method to extract and Option() object from the Config() @@ -502,11 +504,12 @@ def mandatory_warnings(config): :returns: generator of mandatory Option's path """ - config.cfgimpl_reset_cache() + #if value in cache, properties are not calculated + config.cfgimpl_reset_cache(only=('values',)) for path in config.cfgimpl_get_description().getpaths(include_groups=True): try: config._getattr(path, force_properties=('mandatory',)) except PropertiesOptionError, err: if err.proptype == ['mandatory']: yield path - config.cfgimpl_reset_cache() + config.cfgimpl_reset_cache(only=('values',)) diff --git a/tiramisu/setting.py b/tiramisu/setting.py index 2f51706..97098b4 100644 --- a/tiramisu/setting.py +++ b/tiramisu/setting.py @@ -157,23 +157,31 @@ class Setting(object): #____________________________________________________________ # properties methods - def has_properties(self, opt=None, is_apply_req=True): + def has_properties(self, opt=None): "has properties means the Config's properties attribute is not empty" - return bool(len(self.get_properties(opt, is_apply_req))) + return bool(len(self.get_properties(opt))) def get_properties(self, opt=None, is_apply_req=True): + if opt is not None and opt in self._cache: + exp = time() + props, created = self._cache[opt] + if exp < created: + return props if opt is None: default = [] else: if is_apply_req: apply_requires(opt, self.context) default = list(opt._properties) - return self.properties.get(opt, default) + props = self.properties.get(opt, default) + if opt is not None: + self._set_cache(opt, props) + return props - def has_property(self, propname, opt=None, is_apply_req=True): + def has_property(self, propname, opt=None): """has property propname in the Config's properties attribute :param property: string wich is the name of the property""" - return propname in self.get_properties(opt, is_apply_req) + return propname in self.get_properties(opt) def enable_property(self, propname): "puts property propname in the Config's properties attribute" @@ -205,6 +213,8 @@ class Setting(object): self.properties[opt] = properties def add_property(self, propname, opt, is_apply_req=True): + if opt is None: + raise ValueError("option must not be None in add_property") properties = self.get_properties(opt, is_apply_req) if not propname in properties: properties.append(propname) @@ -212,6 +222,8 @@ class Setting(object): self.context.cfgimpl_reset_cache() def del_property(self, propname, opt, is_apply_req=True): + if opt is None: + raise ValueError("option must not be None in del_property") properties = self.get_properties(opt, is_apply_req) if propname in properties: properties.remove(propname) @@ -223,7 +235,7 @@ class Setting(object): if force_properties is not None: set_mandatory = ('mandatory' in force_properties or set_mandatory) - if set_mandatory and self.has_property('mandatory', opt, False) and \ + if set_mandatory and self.has_property('mandatory', opt) and \ self.context.cfgimpl_get_values()._is_empty(opt, value): return True return False @@ -232,12 +244,11 @@ class Setting(object): properties = set(self.get_properties(opt_or_descr)) #remove this properties, those properties are validate in after properties = properties - set(['mandatory', 'frozen']) - set_properties = self.get_properties() + set_properties = set(self.get_properties()) if force_properties is not None: - set_properties.extend(force_properties) - set_properties = set(set_properties) + set_properties.update(set(force_properties)) properties = properties & set_properties - if force_permissive is True or self.has_property('permissive', is_apply_req=False): + if force_permissive is True or self.has_property('permissive'): properties = properties - set(self.get_permissive()) properties = properties - set(self.get_permissive(opt_or_descr)) return list(properties) @@ -246,32 +257,22 @@ class Setting(object): def validate_properties(self, opt_or_descr, is_descr, is_write, value=None, force_permissive=False, force_properties=None): - is_cached = False - if opt_or_descr in self._cache: - exp = time() - props, raise_text, created = self._cache[opt_or_descr] - if exp < created: - properties = props - is_cached = True - if not is_cached: - properties = self._calc_properties(opt_or_descr, force_permissive, - force_properties) - raise_text = _("trying to access" - " to an option named: {0} with properties" - " {1}") - if not is_descr: - if self._validate_mandatory(opt_or_descr, value, - force_properties=force_properties): - properties.append('mandatory') - #frozen - if is_write and (self.has_property('everything_frozen') or ( - self.has_property('frozen') and - self.has_property('frozen', opt_or_descr, - is_apply_req=False))): - properties.append('frozen') - raise_text = _('cannot change the value to {0} for ' - 'option {1} this option is frozen') - self._set_cache(opt_or_descr, properties, raise_text) + properties = self._calc_properties(opt_or_descr, force_permissive, + force_properties) + raise_text = _("trying to access" + " to an option named: {0} with properties" + " {1}") + if not is_descr: + if self._validate_mandatory(opt_or_descr, value, + force_properties=force_properties): + properties.append('mandatory') + #frozen + if is_write and (self.has_property('everything_frozen') or ( + self.has_property('frozen') and + self.has_property('frozen', opt_or_descr))): + properties.append('frozen') + raise_text = _('cannot change the value to {0} for ' + 'option {1} this option is frozen') if properties != []: raise PropertiesOptionError(raise_text.format(opt_or_descr._name, str(properties)), @@ -316,16 +317,17 @@ class Setting(object): self.enable_property('validator') self.disable_property('permissive') - def _set_cache(self, opt, props, raise_text): + def _set_cache(self, opt, props): if self.has_property('expire'): - self._cache[opt] = (props, raise_text, time() + expires_time) + self._cache[opt] = (props, time() + expires_time) + pass def reset_cache(self, only_expired): if only_expired: exp = time() keys = self._cache.keys() for key in keys: - props, raise_text, created = self._cache[key] + props, created = self._cache[key] if exp > created: del(self._cache[key]) else: diff --git a/tiramisu/value.py b/tiramisu/value.py index 5b0aeae..bfa79ac 100644 --- a/tiramisu/value.py +++ b/tiramisu/value.py @@ -96,14 +96,14 @@ class Values(object): # options with callbacks setting = self.context.cfgimpl_get_settings() value = self._get_value(opt) - is_frozen = setting.has_property('frozen', opt, False) + is_frozen = setting.has_property('frozen', opt) if opt.has_callback(): #if value is set and : # - not frozen # - frozen and not force_default_on_freeze if not self.is_default_owner(opt) and ( not is_frozen or (is_frozen and - not setting.has_property('force_default_on_freeze', opt, False))): + not setting.has_property('force_default_on_freeze', opt))): pass else: value = self._getcallback_value(opt) @@ -112,7 +112,7 @@ class Values(object): #suppress value if already set self._reset(opt) # frozen and force default - elif is_frozen and setting.has_property('force_default_on_freeze', opt, False): + elif is_frozen and setting.has_property('force_default_on_freeze', opt): value = opt.getdefault() if opt.is_multi(): value = Multi(value, self.context, opt) @@ -120,7 +120,7 @@ class Values(object): raise ValueError(_('invalid calculated value returned' ' for option {0}: {1}').format(opt._name, value)) if self.is_default_owner(opt) and \ - setting.has_property('force_store_value', opt, False): + setting.has_property('force_store_value', opt): self.setitem(opt, value) setting.validate_properties(opt, False, False, value=value, force_permissive=force_permissive,