diff --git a/ChangeLog b/ChangeLog index 23913bc..8cb44d7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,10 +1,12 @@ Sat Apr 12 11:37:27 CEST 2014 Emmanuel Garette * behavior change in master/slave part of code: - if slave has a default value greater than master's one, it's raise - SlaveError, didn't try to reduce the slave's length + if slave has a default value greater than master's one, it's raise + SlaveError, didn't try to reduce the slave's length + * tiramisu/config.py (in cfgimpl_get_home_by_path and getattr) and + tiramisu/value.py (in getitem): arity change, remove force_properties * tiramisu/option.py: split into tiramisu/option directory * tiramisu/option/masterslave.py: master/slaves have no a special - object MasterSlaves for all code related to master/slaves options + object MasterSlaves for all code related to master/slaves options * tiramisu/option/masterslave.py: master and slaves values (length, - consistency, ...) are now check every time + consistency, ...) are now check every time diff --git a/test/test_mandatory.py b/test/test_mandatory.py index 26c8e4b..59da145 100644 --- a/test/test_mandatory.py +++ b/test/test_mandatory.py @@ -1,4 +1,5 @@ import autopath +from time import sleep #from py.test import raises from tiramisu.config import Config @@ -205,11 +206,12 @@ def test_mandatory_warnings_ro(): except PropertiesOptionError as err: proc = err.proptype assert proc == ['mandatory'] - assert list(config.cfgimpl_get_values().mandatory_warnings()) == ['str', 'str1', 'unicode2', 'str3'] + assert config.cfgimpl_get_values().mandatory_warnings() == ['str', 'str1', 'unicode2', 'str3'] config.read_write() config.str = 'a' config.read_only() - assert list(config.cfgimpl_get_values().mandatory_warnings()) == ['str1', 'unicode2', 'str3'] + assert config.cfgimpl_get_values().mandatory_warnings() == ['str1', 'unicode2', 'str3'] + sleep(.1) def test_mandatory_warnings_rw(): @@ -218,9 +220,10 @@ def test_mandatory_warnings_rw(): config.str = '' config.read_write() config.str - assert list(config.cfgimpl_get_values().mandatory_warnings()) == ['str', 'str1', 'unicode2', 'str3'] + assert config.cfgimpl_get_values().mandatory_warnings() == ['str', 'str1', 'unicode2', 'str3'] config.str = 'a' - assert list(config.cfgimpl_get_values().mandatory_warnings()) == ['str1', 'unicode2', 'str3'] + assert config.cfgimpl_get_values().mandatory_warnings() == ['str1', 'unicode2', 'str3'] + sleep(.1) def test_mandatory_warnings_disabled(): @@ -230,9 +233,10 @@ def test_mandatory_warnings_disabled(): setting = config.cfgimpl_get_settings() config.read_write() config.str - assert list(config.cfgimpl_get_values().mandatory_warnings()) == ['str', 'str1', 'unicode2', 'str3'] + assert config.cfgimpl_get_values().mandatory_warnings() == ['str', 'str1', 'unicode2', 'str3'] setting[descr.str].append('disabled') - assert list(config.cfgimpl_get_values().mandatory_warnings()) == ['str1', 'unicode2', 'str3'] + assert config.cfgimpl_get_values().mandatory_warnings() == ['str1', 'unicode2', 'str3'] + sleep(.1) def test_mandatory_warnings_frozen(): @@ -242,7 +246,8 @@ def test_mandatory_warnings_frozen(): setting = config.cfgimpl_get_settings() config.read_write() config.str - assert list(config.cfgimpl_get_values().mandatory_warnings()) == ['str', 'str1', 'unicode2', 'str3'] + assert config.cfgimpl_get_values().mandatory_warnings() == ['str', 'str1', 'unicode2', 'str3'] setting[descr.str].append('frozen') config.read_only() - assert list(config.cfgimpl_get_values().mandatory_warnings()) == ['str', 'str1', 'unicode2', 'str3'] + assert config.cfgimpl_get_values().mandatory_warnings() == ['str', 'str1', 'unicode2', 'str3'] + sleep(.1) diff --git a/tiramisu/config.py b/tiramisu/config.py index 04c9cb9..b6e919b 100644 --- a/tiramisu/config.py +++ b/tiramisu/config.py @@ -62,14 +62,12 @@ class SubConfig(object): "remove cache (in context)" self._cfgimpl_get_context().cfgimpl_reset_cache(only_expired, only) - def cfgimpl_get_home_by_path(self, path, force_permissive=False, - force_properties=None): + def cfgimpl_get_home_by_path(self, path, force_permissive=False): """:returns: tuple (config, name)""" path = path.split('.') for step in path[:-1]: self = self.getattr(step, - force_permissive=force_permissive, - force_properties=force_properties) + force_permissive=force_permissive) return self, path[-1] def __hash__(self): @@ -214,29 +212,24 @@ class SubConfig(object): def __getattr__(self, name): return self.getattr(name) - def _getattr(self, name, force_permissive=False, force_properties=None, - validate=True): + def _getattr(self, name, force_permissive=False, validate=True): """use getattr instead of _getattr """ - return self.getattr(name, force_permissive, force_properties, validate) + return self.getattr(name, force_permissive, validate) - def getattr(self, name, force_permissive=False, force_properties=None, - validate=True): + def getattr(self, name, force_permissive=False, validate=True): """ attribute notation mechanism for accessing the value of an option :param name: attribute name :return: option's value if name is an option name, OptionDescription otherwise """ - #FIXME force_properties vraiment utile maintenant ? # attribute access by passing a path, # for instance getattr(self, "creole.general.family.adresse_ip_eth0") if '.' in name: homeconfig, name = self.cfgimpl_get_home_by_path( - name, force_permissive=force_permissive, - force_properties=force_properties) + name, force_permissive=force_permissive) return homeconfig.getattr(name, force_permissive=force_permissive, - force_properties=force_properties, validate=validate) opt_or_descr = getattr(self.cfgimpl_get_description(), name) if self._impl_path is None: @@ -251,19 +244,16 @@ class SubConfig(object): path = context.cfgimpl_get_description().impl_get_path_by_opt( opt_or_descr._opt) return context.getattr(path, validate=validate, - force_properties=force_properties, force_permissive=force_permissive) elif isinstance(opt_or_descr, OptionDescription): self.cfgimpl_get_settings().validate_properties( opt_or_descr, True, False, path=subpath, - force_permissive=force_permissive, - force_properties=force_properties) + force_permissive=force_permissive) return SubConfig(opt_or_descr, self._impl_context, subpath) else: return self.cfgimpl_get_values()._get_cached_item( opt_or_descr, path=subpath, validate=validate, - force_properties=force_properties, force_permissive=force_permissive) def find(self, bytype=None, byname=None, byvalue=None, type_='option', diff --git a/tiramisu/value.py b/tiramisu/value.py index 47e74b6..9b954a5 100644 --- a/tiramisu/value.py +++ b/tiramisu/value.py @@ -22,7 +22,7 @@ from tiramisu.error import ConfigError, SlaveError, PropertiesOptionError from tiramisu.setting import owners, expires_time, undefined from tiramisu.autolib import carry_out_calculation from tiramisu.i18n import _ -from tiramisu.option import SymLinkOption +from tiramisu.option import SymLinkOption, OptionDescription class Values(object): @@ -170,13 +170,11 @@ class Values(object): "enables us to use the pythonic dictionary-like access to values" return self.getitem(opt) - def getitem(self, opt, validate=True, force_permissive=False, - force_properties=None): + def getitem(self, opt, validate=True, force_permissive=False): """ """ return self._get_cached_item(opt, validate=validate, - force_permissive=force_permissive, - force_properties=force_properties) + force_permissive=force_permissive) def _get_cached_item(self, opt, path=None, validate=True, force_permissive=False, force_properties=None, @@ -296,7 +294,6 @@ class Values(object): is_write=is_write) def _setvalue(self, opt, path, value, force_permissive=False, - force_properties=None, is_write=True, validate_properties=True): context = self._getcontext() context.cfgimpl_reset_cache() @@ -304,8 +301,7 @@ class Values(object): setting = context.cfgimpl_get_settings() setting.validate_properties(opt, False, is_write, value=value, path=path, - force_permissive=force_permissive, - force_properties=force_properties) + force_permissive=force_permissive) owner = context.cfgimpl_get_settings().getowner() if isinstance(value, Multi): value = list(value) @@ -421,18 +417,26 @@ class Values(object): :returns: generator of mandatory Option's path """ - #if value in cache, properties are not calculated + def _mandatory_warnings(description): + #if value in cache, properties are not calculated + for opt in description.impl_getchildren(): + if isinstance(opt, OptionDescription): + _mandatory_warnings(opt) + elif isinstance(opt, SymLinkOption): + pass + else: + path = self._get_opt_path(opt) + try: + self._get_cached_item(opt, path=path, + force_properties=frozenset(('mandatory',))) + except PropertiesOptionError as err: + if err.proptype == ['mandatory']: + yield path self.reset_cache(False) - context = self.context() - for path in context.cfgimpl_get_description().impl_getpaths( - include_groups=True): - try: - context.getattr(path, - force_properties=frozenset(('mandatory',))) - except PropertiesOptionError as err: - if err.proptype == ['mandatory']: - yield path + descr = self._getcontext().cfgimpl_get_description() + ret = list(_mandatory_warnings(descr)) self.reset_cache(False) + return ret def force_cache(self): """parse all option to force data in cache