merge from master

This commit is contained in:
Emmanuel Garette 2013-08-20 16:33:32 +02:00
commit ace7f6f828
5 changed files with 209 additions and 107 deletions

View File

@ -152,7 +152,8 @@ class SubConfig(BaseInformation):
def cfgimpl_get_description(self): def cfgimpl_get_description(self):
if self._impl_descr is None: if self._impl_descr is None:
raise ConfigError(_('no optiondescription for this config (may be metaconfig without meta)')) raise ConfigError(_('no option description found for this config'
' (may be metaconfig without meta)'))
else: else:
return self._impl_descr return self._impl_descr
@ -182,7 +183,9 @@ class SubConfig(BaseInformation):
force_permissive=force_permissive) force_permissive=force_permissive)
else: else:
context = self.cfgimpl_get_context() context = self.cfgimpl_get_context()
path = context.cfgimpl_get_description().impl_get_path_by_opt(child._opt) path = context.\
cfgimpl_get_description().\
impl_get_path_by_opt(child._opt)
context._setattr(path, value, force_permissive=force_permissive) context._setattr(path, value, force_permissive=force_permissive)
def __delattr__(self, name): def __delattr__(self, name):
@ -204,8 +207,8 @@ class SubConfig(BaseInformation):
# for instance getattr(self, "creole.general.family.adresse_ip_eth0") # for instance getattr(self, "creole.general.family.adresse_ip_eth0")
if '.' in name: if '.' in name:
homeconfig, name = self.cfgimpl_get_home_by_path(name, homeconfig, name = self.cfgimpl_get_home_by_path(name,
force_permissive=force_permissive, force_permissive=force_permissive,
force_properties=force_properties) force_properties=force_properties)
return homeconfig._getattr(name, force_permissive=force_permissive, return homeconfig._getattr(name, force_permissive=force_permissive,
force_properties=force_properties, force_properties=force_properties,
validate=validate) validate=validate)
@ -218,21 +221,22 @@ class SubConfig(BaseInformation):
# symlink options # symlink options
if isinstance(opt_or_descr, SymLinkOption): if isinstance(opt_or_descr, SymLinkOption):
context = self.cfgimpl_get_context() context = self.cfgimpl_get_context()
path = context.cfgimpl_get_description().impl_get_path_by_opt(opt_or_descr._opt) path = context.cfgimpl_get_description(
).impl_get_path_by_opt(opt_or_descr._opt)
return context._getattr(path, validate=validate, return context._getattr(path, validate=validate,
force_properties=force_properties, force_properties=force_properties,
force_permissive=force_permissive) force_permissive=force_permissive)
elif isinstance(opt_or_descr, OptionDescription): elif isinstance(opt_or_descr, OptionDescription):
self.cfgimpl_get_settings().validate_properties(opt_or_descr, self.cfgimpl_get_settings().validate_properties(opt_or_descr,
True, False, True, False,
force_permissive=force_permissive, force_permissive=force_permissive,
force_properties=force_properties) force_properties=force_properties)
return SubConfig(opt_or_descr, self.cfgimpl_get_context()) return SubConfig(opt_or_descr, self.cfgimpl_get_context())
else: else:
return self.cfgimpl_get_values().getitem(opt_or_descr, return self.cfgimpl_get_values().getitem(opt_or_descr,
validate=validate, validate=validate,
force_properties=force_properties, force_properties=force_properties,
force_permissive=force_permissive) force_permissive=force_permissive)
def find(self, bytype=None, byname=None, byvalue=None, type_='option'): def find(self, bytype=None, byname=None, byvalue=None, type_='option'):
""" """
@ -246,7 +250,8 @@ class SubConfig(BaseInformation):
return self.cfgimpl_get_context()._find(bytype, byname, byvalue, return self.cfgimpl_get_context()._find(bytype, byname, byvalue,
first=False, first=False,
type_=type_, type_=type_,
_subpath=self.cfgimpl_get_path()) _subpath=self.cfgimpl_get_path()
)
def find_first(self, bytype=None, byname=None, byvalue=None, def find_first(self, bytype=None, byname=None, byvalue=None,
type_='option', display_error=True): type_='option', display_error=True):
@ -259,10 +264,10 @@ class SubConfig(BaseInformation):
:returns: list of matching Option objects :returns: list of matching Option objects
""" """
return self.cfgimpl_get_context()._find(bytype, byname, byvalue, return self.cfgimpl_get_context()._find(bytype, byname, byvalue,
first=True, first=True,
type_=type_, type_=type_,
_subpath=self.cfgimpl_get_path(), _subpath=self.cfgimpl_get_path(),
display_error=display_error) display_error=display_error)
def _find(self, bytype, byname, byvalue, first, type_='option', def _find(self, bytype, byname, byvalue, first, type_='option',
_subpath=None, check_properties=True, display_error=True): _subpath=None, check_properties=True, display_error=True):
@ -274,7 +279,8 @@ class SubConfig(BaseInformation):
""" """
def _filter_by_name(): def _filter_by_name():
try: try:
if byname is None or path == byname or path.endswith('.' + byname): if byname is None or path == byname or \
path.endswith('.' + byname):
return True return True
except IndexError: except IndexError:
pass pass
@ -287,7 +293,8 @@ class SubConfig(BaseInformation):
value = getattr(self, path) value = getattr(self, path)
if value == byvalue: if value == byvalue:
return True return True
except PropertiesOptionError: # a property restricts the access of the value except PropertiesOptionError: # a property is a restriction
# upon the access of the value
pass pass
return False return False
@ -310,7 +317,8 @@ class SubConfig(BaseInformation):
# return False # return False
# return False # return False
if type_ not in ('option', 'path', 'context', 'value'): if type_ not in ('option', 'path', 'context', 'value'):
raise ValueError(_('unknown type_ type {0} for _find').format(type_)) raise ValueError(_('unknown type_ type {0}'
'for _find').format(type_))
find_results = [] find_results = []
opts, paths = self.cfgimpl_get_description()._cache_paths opts, paths = self.cfgimpl_get_description()._cache_paths
for index in range(0, len(paths)): for index in range(0, len(paths)):
@ -349,7 +357,8 @@ class SubConfig(BaseInformation):
find_results.append(retval) find_results.append(retval)
if find_results == []: if find_results == []:
if display_error: if display_error:
raise AttributeError(_("no option found in config with these criteria")) raise AttributeError(_("no option found in config"
" with these criteria"))
else: else:
#translation is slow #translation is slow
raise AttributeError() raise AttributeError()
@ -375,15 +384,21 @@ class SubConfig(BaseInformation):
`OptionDescription` than the `withoption` itself:: `OptionDescription` than the `withoption` itself::
>>> print cfg.make_dict(withoption='var1') >>> print cfg.make_dict(withoption='var1')
{'od2.var4': None, 'od2.var5': None, 'od2.var6': None, {'od2.var4': None, 'od2.var5': None,
'od2.var1': u'value', 'od1.var1': None, 'od2.var6': None,
'od1.var3': None, 'od1.var2': None} 'od2.var1': u'value',
'od1.var1': None,
'od1.var3': None,
'od1.var2': None}
:param withvalue: returns the options that have the value `withvalue` :param withvalue: returns the options that have the value `withvalue`
:: ::
>>> print c.make_dict(withoption='var1', withvalue=u'value') >>> print c.make_dict(withoption='var1',
{'od2.var4': None, 'od2.var5': None, 'od2.var6': None, withvalue=u'value')
{'od2.var4': None,
'od2.var5': None,
'od2.var6': None,
'od2.var1': u'value'} 'od2.var1': u'value'}
:returns: dict of Option's name (or path) and values :returns: dict of Option's name (or path) and values
@ -403,7 +418,9 @@ class SubConfig(BaseInformation):
type_='path', type_='path',
_subpath=mypath): _subpath=mypath):
path = '.'.join(path.split('.')[:-1]) path = '.'.join(path.split('.')[:-1])
opt = self.cfgimpl_get_context().cfgimpl_get_description().impl_get_opt_by_path(path) opt = self.cfgimpl_get_context(
).cfgimpl_get_description(
).impl_get_opt_by_path(path)
if mypath is not None: if mypath is not None:
if mypath == path: if mypath == path:
withoption = None withoption = None
@ -431,7 +448,8 @@ class SubConfig(BaseInformation):
if isinstance(opt, OptionDescription): if isinstance(opt, OptionDescription):
try: try:
pathsvalues += getattr(self, path).make_dict(flatten, pathsvalues += getattr(self, path).make_dict(flatten,
_currpath + path.split('.')) _currpath +
path.split('.'))
except PropertiesOptionError: except PropertiesOptionError:
pass # this just a hidden or disabled option pass # this just a hidden or disabled option
else: else:
@ -481,8 +499,9 @@ class CommonConfig(SubConfig):
:returns: Option() :returns: Option()
""" """
if '.' in path: if '.' in path:
homeconfig, path = self.cfgimpl_get_home_by_path(path, homeconfig, path = self.cfgimpl_get_home_by_path(
force_permissive=force_permissive) path,
force_permissive=force_permissive)
return getattr(homeconfig.cfgimpl_get_description(), path) return getattr(homeconfig.cfgimpl_get_description(), path)
return getattr(self.cfgimpl_get_description(), path) return getattr(self.cfgimpl_get_description(), path)
@ -514,7 +533,9 @@ class Config(CommonConfig):
self._impl_meta = None self._impl_meta = None
self._impl_informations = {} self._impl_informations = {}
def cfgimpl_reset_cache(self, only_expired=False, only=('values', 'settings')): def cfgimpl_reset_cache(self,
only_expired=False,
only=('values', 'settings')):
if 'values' in only: if 'values' in only:
self.cfgimpl_get_values().reset_cache(only_expired=only_expired) self.cfgimpl_get_values().reset_cache(only_expired=only_expired)
if 'settings' in only: if 'settings' in only:
@ -531,13 +552,14 @@ class MetaConfig(CommonConfig):
if meta: if meta:
for child in children: for child in children:
if not isinstance(child, CommonConfig): if not isinstance(child, CommonConfig):
raise ValueError(_("metaconfig's children must be config, not {0}" raise ValueError(_("metaconfig's children "
"").format(type(child))) "must be config, not {0}"
).format(type(child)))
if self._impl_descr is None: if self._impl_descr is None:
self._impl_descr = child.cfgimpl_get_description() self._impl_descr = child.cfgimpl_get_description()
elif not self._impl_descr is child.cfgimpl_get_description(): elif not self._impl_descr is child.cfgimpl_get_description():
raise ValueError(_('all config in metaconfig must have same ' raise ValueError(_('all config in metaconfig must '
'optiondescription')) 'have the same optiondescription'))
if child.cfgimpl_get_meta() is not None: if child.cfgimpl_get_meta() is not None:
raise ValueError(_("child has already a metaconfig's")) raise ValueError(_("child has already a metaconfig's"))
child._impl_meta = self child._impl_meta = self
@ -556,7 +578,9 @@ class MetaConfig(CommonConfig):
"a meta config is a config wich has a setting, that is itself" "a meta config is a config wich has a setting, that is itself"
return self return self
def cfgimpl_reset_cache(self, only_expired=False, only=('values', 'settings')): def cfgimpl_reset_cache(self,
only_expired=False,
only=('values', 'settings')):
if 'values' in only: if 'values' in only:
self.cfgimpl_get_values().reset_cache(only_expired=only_expired) self.cfgimpl_get_values().reset_cache(only_expired=only_expired)
if 'settings' in only: if 'settings' in only:
@ -621,7 +645,8 @@ def mandatory_warnings(config):
""" """
#if value in cache, properties are not calculated #if value in cache, properties are not calculated
config.cfgimpl_reset_cache(only=('values',)) config.cfgimpl_reset_cache(only=('values',))
for path in config.cfgimpl_get_description().impl_getpaths(include_groups=True): for path in config.cfgimpl_get_description(
).impl_getpaths(include_groups=True):
try: try:
config._getattr(path, force_properties=frozenset(('mandatory',))) config._getattr(path, force_properties=frozenset(('mandatory',)))
except PropertiesOptionError, err: except PropertiesOptionError, err:

View File

@ -20,6 +20,8 @@
# the whole pypy projet is under MIT licence # the whole pypy projet is under MIT licence
# ____________________________________________________________ # ____________________________________________________________
"user defined exceptions" "user defined exceptions"
# Exceptions for an Option # Exceptions for an Option
class PropertiesOptionError(AttributeError): class PropertiesOptionError(AttributeError):
"attempt to access to an option with a property that is not allowed" "attempt to access to an option with a property that is not allowed"

View File

@ -68,7 +68,8 @@ class BaseInformation(object):
self._impl_informations[key] = value self._impl_informations[key] = value
except AttributeError: except AttributeError:
raise AttributeError(_('{0} has no attribute ' raise AttributeError(_('{0} has no attribute '
'impl_set_information').format(self.__class__.__name__)) 'impl_set_information').format(
self.__class__.__name__))
def impl_get_information(self, key, default=None): def impl_get_information(self, key, default=None):
"""retrieves one information's item """retrieves one information's item
@ -81,10 +82,12 @@ class BaseInformation(object):
elif default is not None: elif default is not None:
return default return default
else: else:
raise ValueError(_("Information's item not found: {0}").format(key)) raise ValueError(_("Information's item"
"not found: {0}").format(key))
except AttributeError: except AttributeError:
raise AttributeError(_('{0} has no attribute ' raise AttributeError(_('{0} has no attribute '
'impl_get_information').format(self.__class__.__name__)) 'impl_get_information').format(
self.__class__.__name__))
class Option(BaseInformation): class Option(BaseInformation):
@ -93,8 +96,10 @@ class Option(BaseInformation):
Reminder: an Option object is **not** a container for the value Reminder: an Option object is **not** a container for the value
""" """
__slots__ = ('_name', '_requires', '_multi', '_validator', '_default_multi', __slots__ = ('_name', '_requires', '_multi', '_validator',
'_default', '_properties', '_callback', '_multitype', '_default_multi',
'_default',
'_properties', '_callback', '_multitype',
'_master_slaves', '_consistencies', '_empty') '_master_slaves', '_consistencies', '_empty')
_empty = '' _empty = ''
@ -145,13 +150,16 @@ class Option(BaseInformation):
self._validate(default_multi) self._validate(default_multi)
except ValueError, err: except ValueError, err:
raise ValueError(_("invalid default_multi value {0} " raise ValueError(_("invalid default_multi value {0} "
"for option {1}: {2}").format(str(default_multi), name, err)) "for option {1}: {2}").format(
if callback is not None and (default is not None or default_multi is not None): str(default_multi), name, err))
if callback is not None and (default is not None or
default_multi is not None):
raise ValueError(_("default value not allowed if option: {0} " raise ValueError(_("default value not allowed if option: {0} "
"is calculated").format(name)) "is calculated").format(name))
if callback is None and callback_params is not None: if callback is None and callback_params is not None:
raise ValueError(_("params defined for a callback function but " raise ValueError(_("params defined for a callback function but "
"no callback defined yet for option {0}").format(name)) "no callback defined"
" yet for option {0}").format(name))
if callback is not None: if callback is not None:
if type(callback) != FunctionType: if type(callback) != FunctionType:
raise ValueError('callback must be a function') raise ValueError('callback must be a function')
@ -172,14 +180,18 @@ class Option(BaseInformation):
properties = tuple() properties = tuple()
if not isinstance(properties, tuple): if not isinstance(properties, tuple):
raise TypeError(_('invalid properties type {0} for {1},' raise TypeError(_('invalid properties type {0} for {1},'
' must be a tuple').format(type(properties), self._name)) ' must be a tuple').format(
type(properties),
self._name))
self._properties = properties # 'hidden', 'disabled'... self._properties = properties # 'hidden', 'disabled'...
def __eq__(self, other): def __eq__(self, other):
"Option comparison" "Option comparison"
if not isinstance(other, Option): if not isinstance(other, Option):
return False return False
slots = list(self.__slots__ + Option.__slots__ + BaseInformation.__slots__) slots = list(self.__slots__ +
Option.__slots__ +
BaseInformation.__slots__)
for var in slots: for var in slots:
try: try:
val1 = getattr(self, var) val1 = getattr(self, var)
@ -270,8 +282,11 @@ class Option(BaseInformation):
if _value is None: if _value is None:
return True return True
if not val_validator(_value): if not val_validator(_value):
raise ValueError(_("invalid value {0} for option {1} for object {2}" raise ValueError(_("invalid value {0} "
"").format(_value, self._name, self.__class__.__name__)) "for option {1} for object {2}"
).format(_value,
self._name,
self.__class__.__name__))
try: try:
self._validate(_value) self._validate(_value)
except ValueError, err: except ValueError, err:
@ -314,7 +329,8 @@ class Option(BaseInformation):
def impl_is_empty_by_default(self): def impl_is_empty_by_default(self):
"no default value has been set yet" "no default value has been set yet"
if ((not self.impl_is_multi() and self._default is None) or if ((not self.impl_is_multi() and self._default is None) or
(self.impl_is_multi() and (self._default == [] or None in self._default))): (self.impl_is_multi() and (self._default == []
or None in self._default))):
return True return True
return False return False
@ -343,9 +359,13 @@ class Option(BaseInformation):
if self is opt: if self is opt:
raise ValueError('cannot add consistency with itself') raise ValueError('cannot add consistency with itself')
if self.impl_is_multi() != opt.impl_is_multi(): if self.impl_is_multi() != opt.impl_is_multi():
raise ValueError('options in consistency should be multi in two sides') raise ValueError('options in consistency'
' should be multi in two sides')
func = '_cons_{0}'.format(func) func = '_cons_{0}'.format(func)
self._launch_consistency(func, self, self.impl_getdefault(), None, None, opt) self._launch_consistency(func,
self,
self.impl_getdefault(),
None, None, opt)
self._consistencies.append((func, opt)) self._consistencies.append((func, opt))
self.impl_validate(self.impl_getdefault()) self.impl_validate(self.impl_getdefault())
@ -397,7 +417,8 @@ class ChoiceOption(Option):
def _validate(self, value): def _validate(self, value):
if not self._open_values and not value in self._values: if not self._open_values and not value in self._values:
raise ValueError(_('value {0} is not permitted, only {1} is allowed' raise ValueError(_('value {0} is not permitted, '
'only {1} is allowed'
'').format(value, self._values)) '').format(value, self._values))
@ -462,7 +483,8 @@ class SymLinkOption(object):
self._name = name self._name = name
if not isinstance(opt, Option): if not isinstance(opt, Option):
raise ValueError(_('malformed symlinkoption ' raise ValueError(_('malformed symlinkoption '
'must be an option for symlink {0}').format(name)) 'must be an option '
'for symlink {0}').format(name))
self._opt = opt self._opt = opt
def __getattr__(self, name): def __getattr__(self, name):
@ -526,7 +548,10 @@ class PortOption(Option):
ports_min = [0, 1, 1024, 49152] ports_min = [0, 1, 1024, 49152]
ports_max = [0, 1023, 49151, 65535] ports_max = [0, 1023, 49151, 65535]
is_finally = False is_finally = False
for index, allowed in enumerate([allow_zero, allow_wellknown, allow_registred, allow_private]): for index, allowed in enumerate([allow_zero,
allow_wellknown,
allow_registred,
allow_private]):
if self._min_value is None: if self._min_value is None:
if allowed: if allowed:
self._min_value = ports_min[index] self._min_value = ports_min[index]
@ -556,7 +581,8 @@ class PortOption(Option):
if len(value) != 2: if len(value) != 2:
raise ValueError('range must have two values only') raise ValueError('range must have two values only')
if not value[0] < value[1]: if not value[0] < value[1]:
raise ValueError('first port in range must be smaller than the second one') raise ValueError('first port in range must be'
' smaller than the second one')
else: else:
value = [value] value = [value]
@ -606,7 +632,8 @@ class NetmaskOption(Option):
make_net=not make_net) make_net=not make_net)
except ValueError: except ValueError:
if not make_net: if not make_net:
msg = _("invalid network {0} ({1}) with netmask {2} ({3})," msg = _("invalid network {0} ({1}) "
"with netmask {2} ({3}),"
" this network is an IP") " this network is an IP")
else: else:
if make_net: if make_net:
@ -672,7 +699,8 @@ class DomainnameOption(Option):
raise ValueError(_("invalid value for {0}, must have dot" raise ValueError(_("invalid value for {0}, must have dot"
"").format(self._name)) "").format(self._name))
if len(value) > length: if len(value) > length:
raise ValueError(_("invalid domainname's length for {0} (max {1})").format(self._name, length)) raise ValueError(_("invalid domainname's length for "
" {0} (max {1})").format(self._name, length))
if len(value) == 1: if len(value) == 1:
raise ValueError(_("invalid domainname's length for {0} (min 2)" raise ValueError(_("invalid domainname's length for {0} (min 2)"
"").format(self._name)) "").format(self._name))
@ -694,7 +722,8 @@ class OptionDescription(BaseInformation):
""" """
if not valid_name(name): if not valid_name(name):
raise ValueError(_("invalid name: {0} for optiondescription").format(name)) raise ValueError(_("invalid name: "
" {0} for optiondescription").format(name))
self._name = name self._name = name
self._impl_informations = {} self._impl_informations = {}
self.impl_set_information('doc', doc) self.impl_set_information('doc', doc)
@ -717,7 +746,8 @@ class OptionDescription(BaseInformation):
properties = tuple() properties = tuple()
if not isinstance(properties, tuple): if not isinstance(properties, tuple):
raise TypeError(_('invalid properties type {0} for {1},' raise TypeError(_('invalid properties type {0} for {1},'
' must be a tuple').format(type(properties), self._name)) ' must be a tuple').format(type(properties),
self._name))
self._properties = properties # 'hidden', 'disabled'... self._properties = properties # 'hidden', 'disabled'...
# the group_type is useful for filtering OptionDescriptions in a config # the group_type is useful for filtering OptionDescriptions in a config
self._group_type = groups.default self._group_type = groups.default
@ -729,8 +759,9 @@ class OptionDescription(BaseInformation):
try: try:
return self._children[1][self._children[0].index(name)] return self._children[1][self._children[0].index(name)]
except ValueError: except ValueError:
raise AttributeError(_('unknown Option {0} in OptionDescription {1}' raise AttributeError(_('unknown Option {0} '
'').format(name, self._name)) 'in OptionDescription {1}'
'').format(name, self._name))
def impl_getkey(self, config): def impl_getkey(self, config):
return tuple([child.impl_getkey(getattr(config, child._name)) return tuple([child.impl_getkey(getattr(config, child._name))
@ -757,7 +788,11 @@ class OptionDescription(BaseInformation):
def impl_getchildren(self): def impl_getchildren(self):
return self._children[1] return self._children[1]
def impl_build_cache(self, cache_path=None, cache_option=None, _currpath=None, _consistencies=None): def impl_build_cache(self,
cache_path=None,
cache_option=None,
_currpath=None,
_consistencies=None):
if _currpath is None and self._cache_paths is not None: if _currpath is None and self._cache_paths is not None:
return return
if _currpath is None: if _currpath is None:
@ -780,11 +815,16 @@ class OptionDescription(BaseInformation):
for consistency in option._consistencies: for consistency in option._consistencies:
func, opt = consistency func, opt = consistency
opts = (option, opt) opts = (option, opt)
_consistencies.setdefault(opt, []).append((func, opts)) _consistencies.setdefault(opt,
_consistencies.setdefault(option, []).append((func, opts)) []).append((func, opts))
_consistencies.setdefault(option,
[]).append((func, opts))
else: else:
_currpath.append(attr) _currpath.append(attr)
option.impl_build_cache(cache_path, cache_option, _currpath, _consistencies) option.impl_build_cache(cache_path,
cache_option,
_currpath,
_consistencies)
_currpath.pop() _currpath.pop()
if save: if save:
#valid no duplicated option #valid no duplicated option
@ -820,7 +860,8 @@ class OptionDescription(BaseInformation):
""" """
if self._group_type != groups.default: if self._group_type != groups.default:
raise TypeError(_('cannot change group_type if already set ' raise TypeError(_('cannot change group_type if already set '
'(old {0}, new {1})').format(self._group_type, group_type)) '(old {0}, new {1})').format(self._group_type,
group_type))
if isinstance(group_type, groups.GroupType): if isinstance(group_type, groups.GroupType):
self._group_type = group_type self._group_type = group_type
if isinstance(group_type, groups.MasterGroupType): if isinstance(group_type, groups.MasterGroupType):
@ -837,7 +878,8 @@ class OptionDescription(BaseInformation):
raise ValueError(_("master group {0} shall not have " raise ValueError(_("master group {0} shall not have "
"a symlinkoption").format(self._name)) "a symlinkoption").format(self._name))
if not child.impl_is_multi(): if not child.impl_is_multi():
raise ValueError(_("not allowed option {0} in group {1}" raise ValueError(_("not allowed option {0} "
"in group {1}"
": this option is not a multi" ": this option is not a multi"
"").format(child._name, self._name)) "").format(child._name, self._name))
if child._name == self._name: if child._name == self._name:
@ -847,18 +889,20 @@ class OptionDescription(BaseInformation):
else: else:
slaves.append(child) slaves.append(child)
if master is None: if master is None:
raise ValueError(_('master group with wrong master name for {0}' raise ValueError(_('master group with wrong'
'').format(self._name)) ' master name for {0}'
).format(self._name))
master._master_slaves = tuple(slaves) master._master_slaves = tuple(slaves)
for child in self.impl_getchildren(): for child in self.impl_getchildren():
if child != master: if child != master:
child._master_slaves = master child._master_slaves = master
child._multitype = multitypes.slave child._multitype = multitypes.slave
if not identical_master_child_name: if not identical_master_child_name:
raise ValueError(_("no child has same nom has master group " raise ValueError(_("no child has same nom has master group"
"for: {0}").format(self._name)) " for: {0}").format(self._name))
else: else:
raise ValueError(_('not allowed group_type : {0}').format(group_type)) raise ValueError(_('group_type : {0}'
' not allowed').format(group_type))
def impl_get_group_type(self): def impl_get_group_type(self):
return self._group_type return self._group_type
@ -868,8 +912,12 @@ class OptionDescription(BaseInformation):
if consistencies is not None: if consistencies is not None:
for consistency in consistencies: for consistency in consistencies:
opt_ = consistency[1] opt_ = consistency[1]
ret = opt_[0]._launch_consistency(consistency[0], opt, value, context, ret = opt_[0]._launch_consistency(consistency[0],
index, opt_[1]) opt,
value,
context,
index,
opt_[1])
if ret is False: if ret is False:
return False return False
return True return True
@ -931,10 +979,12 @@ def validate_requires_arg(requires, name):
option._validate(expected) option._validate(expected)
except ValueError, err: except ValueError, err:
raise ValueError(_('malformed requirements second argument ' raise ValueError(_('malformed requirements second argument '
'must be valid for option {0}: {1}').format(name, err)) 'must be valid for option {0}'
': {1}').format(name, err))
if action in config_action: if action in config_action:
if inverse != config_action[action]: if inverse != config_action[action]:
raise ValueError(_("inconsistency in action types for option: {0}" raise ValueError(_("inconsistency in action types"
" for option: {0}"
" action: {1}").format(name, action)) " action: {1}").format(name, action))
else: else:
config_action[action] = inverse config_action[action] = inverse
@ -950,7 +1000,11 @@ def validate_requires_arg(requires, name):
for opt_requires in ret_requires.values(): for opt_requires in ret_requires.values():
ret_action = [] ret_action = []
for require in opt_requires.values(): for require in opt_requires.values():
req = (require[0], tuple(require[1]), require[2], require[3], require[4], require[5]) req = (require[0], tuple(require[1]),
require[2],
require[3],
require[4],
require[5])
ret_action.append(req) ret_action.append(req)
ret.append(tuple(ret_action)) ret.append(tuple(ret_action))
return tuple(ret) return tuple(ret)

View File

@ -29,7 +29,8 @@ from tiramisu.i18n import _
default_encoding = 'utf-8' default_encoding = 'utf-8'
expires_time = 5 expires_time = 5
ro_remove = ('permissive', 'hidden') ro_remove = ('permissive', 'hidden')
ro_append = ('frozen', 'disabled', 'validator', 'everything_frozen', 'mandatory') ro_append = ('frozen', 'disabled', 'validator', 'everything_frozen',
'mandatory')
rw_remove = ('permissive', 'everything_frozen', 'mandatory') rw_remove = ('permissive', 'everything_frozen', 'mandatory')
rw_append = ('frozen', 'disabled', 'validator', 'hidden') rw_append = ('frozen', 'disabled', 'validator', 'hidden')
default_properties = ('expire', 'validator') default_properties = ('expire', 'validator')
@ -287,8 +288,8 @@ class Settings(object):
properties -= frozenset(('mandatory', 'frozen')) properties -= frozenset(('mandatory', 'frozen'))
else: else:
if 'mandatory' in properties and \ if 'mandatory' in properties and \
not self.context.cfgimpl_get_values()._isempty(opt_or_descr, not self.context.cfgimpl_get_values()._isempty(
value): opt_or_descr, value):
properties.remove('mandatory') properties.remove('mandatory')
if is_write and 'everything_frozen' in self_properties: if is_write and 'everything_frozen' in self_properties:
properties.add('frozen') properties.add('frozen')
@ -299,12 +300,15 @@ class Settings(object):
props = list(properties) props = list(properties)
if 'frozen' in properties: if 'frozen' in properties:
raise PropertiesOptionError(_('cannot change the value for ' raise PropertiesOptionError(_('cannot change the value for '
'option {0} this option is frozen' 'option {0} this option is'
'').format(opt_or_descr._name), props) ' frozen').format(
opt_or_descr._name),
props)
else: else:
raise PropertiesOptionError(_("trying to access to an option " raise PropertiesOptionError(_("trying to access to an option "
"named: {0} with properties {1}" "named: {0} with properties {1}"
"").format(opt_or_descr._name, str(props)), props) "").format(opt_or_descr._name,
str(props)), props)
#FIXME should be setpermissive #FIXME should be setpermissive
def set_permissive(self, permissive, opt=None): def set_permissive(self, permissive, opt=None):
@ -355,12 +359,13 @@ class Settings(object):
for requires in opt._requires: for requires in opt._requires:
matches = False matches = False
for require in requires: for require in requires:
option, expected, action, inverse, transitive, same_action = require option, expected, action, inverse, \
transitive, same_action = require
path = descr.impl_get_path_by_opt(option) path = descr.impl_get_path_by_opt(option)
if path == optpath or path.startswith(optpath + '.'): if path == optpath or path.startswith(optpath + '.'):
raise RequirementError(_("malformed requirements " raise RequirementError(_("malformed requirements "
"imbrication detected for option: '{0}' " "imbrication detected for option: '{0}' "
"with requirement on: '{1}'").format(optpath, path)) "with requirement on: '{1}'").format(optpath, path))
try: try:
value = self.context._getattr(path, force_permissive=True) value = self.context._getattr(path, force_permissive=True)
except PropertiesOptionError, err: except PropertiesOptionError, err:
@ -368,15 +373,21 @@ class Settings(object):
continue continue
properties = err.proptype properties = err.proptype
if same_action and action not in properties: if same_action and action not in properties:
raise RequirementError(_("option '{0}' has requirement's property error: " raise RequirementError(_("option '{0}' has "
"{1} {2}").format(opt._name, path, properties)) "requirement's property "
"error: "
"{1} {2}").format(opt._name,
path,
properties))
#transitive action, force expected #transitive action, force expected
value = expected[0] value = expected[0]
inverse = False inverse = False
except AttributeError: except AttributeError:
raise AttributeError(_("required option not found: " raise AttributeError(_("required option not found: "
"{0}").format(path)) "{0}").format(path))
if not inverse and value in expected or inverse and value not in expected: if (not inverse and
value in expected or
inverse and value not in expected):
matches = True matches = True
setting.append(action) setting.append(action)
## the calculation cannot be carried out ## the calculation cannot be carried out

View File

@ -95,7 +95,8 @@ class Values(object):
opt.impl_validate(opt.impl_getdefault(), self.context, opt.impl_validate(opt.impl_getdefault(), self.context,
'validator' in setting) 'validator' in setting)
self.context.cfgimpl_reset_cache() self.context.cfgimpl_reset_cache()
if opt.impl_is_multi() and opt.impl_get_multitype() == multitypes.master: if (opt.impl_is_multi() and
opt.impl_get_multitype() == multitypes.master):
for slave in opt.impl_get_master_slaves(): for slave in opt.impl_get_master_slaves():
self.reset(slave) self.reset(slave)
self._p_.resetvalue(key) self._p_.resetvalue(key)
@ -149,14 +150,15 @@ class Values(object):
# options with callbacks # options with callbacks
setting = self.context.cfgimpl_get_settings() setting = self.context.cfgimpl_get_settings()
is_frozen = 'frozen' in setting[opt] is_frozen = 'frozen' in setting[opt]
#if value is callback and is not set or frozen with force_default_on_freeze # if value is callback and is not set
if opt.impl_has_callback() and (self.is_default_owner(opt) or # or frozen with force_default_on_freeze
(is_frozen and if opt.impl_has_callback() and (
'force_default_on_freeze' in setting[opt])): self.is_default_owner(opt) or
(is_frozen and 'force_default_on_freeze' in setting[opt])):
no_value_slave = False no_value_slave = False
if opt.impl_is_multi() and opt.impl_get_multitype() == multitypes.slave: if (opt.impl_is_multi() and
masterp = self.context.cfgimpl_get_description().impl_get_path_by_opt( opt.impl_get_multitype() == multitypes.slave):
opt.impl_get_master_slaves()) masterp = self._get_opt_path(opt.impl_get_master_slaves())
mastervalue = getattr(self.context, masterp) mastervalue = getattr(self.context, masterp)
lenmaster = len(mastervalue) lenmaster = len(mastervalue)
if lenmaster == 0: if lenmaster == 0:
@ -165,7 +167,8 @@ class Values(object):
if not no_value_slave: if not no_value_slave:
value = self._getcallback_value(opt) value = self._getcallback_value(opt)
if opt.impl_is_multi() and opt.impl_get_multitype() == multitypes.slave: if (opt.impl_is_multi() and
opt.impl_get_multitype() == multitypes.slave):
if not isinstance(value, list): if not isinstance(value, list):
value = [value for i in range(lenmaster)] value = [value for i in range(lenmaster)]
if opt.impl_is_multi(): if opt.impl_is_multi():
@ -204,7 +207,8 @@ class Values(object):
self._setvalue(opt, value, force_permissive=force_permissive, self._setvalue(opt, value, force_permissive=force_permissive,
is_write=is_write) is_write=is_write)
def _setvalue(self, opt, value, force_permissive=False, force_properties=None, def _setvalue(self, opt, value, force_permissive=False,
force_properties=None,
is_write=True, validate_properties=True): is_write=True, validate_properties=True):
self.context.cfgimpl_reset_cache() self.context.cfgimpl_reset_cache()
if validate_properties: if validate_properties:
@ -281,13 +285,15 @@ class Multi(list):
self.opt.impl_get_master_slaves()) self.opt.impl_get_master_slaves())
mastervalue = getattr(self.context, masterp) mastervalue = getattr(self.context, masterp)
masterlen = len(mastervalue) masterlen = len(mastervalue)
if len(value) > masterlen or (len(value) < masterlen and valuelen = len(value)
not self.context.cfgimpl_get_values().is_default_owner(self.opt)): if valuelen > masterlen or (valuelen < masterlen and
not self.context.cfgimpl_get_values(
).is_default_owner(self.opt)):
raise SlaveError(_("invalid len for the slave: {0}" raise SlaveError(_("invalid len for the slave: {0}"
" which has {1} as master").format( " which has {1} as master").format(
self.opt._name, masterp)) self.opt._name, masterp))
elif len(value) < masterlen: elif valuelen < masterlen:
for num in range(0, masterlen - len(value)): for num in range(0, masterlen - valuelen):
value.append(self.opt.impl_getdefault_multi()) value.append(self.opt.impl_getdefault_multi())
#else: same len so do nothing #else: same len so do nothing
return value return value
@ -305,7 +311,8 @@ class Multi(list):
self.opt._name, slave._name)) self.opt._name, slave._name))
elif len(value_slave) < masterlen: elif len(value_slave) < masterlen:
for num in range(0, masterlen - len(value_slave)): for num in range(0, masterlen - len(value_slave)):
value_slave.append(slave.impl_getdefault_multi(), force=True) value_slave.append(slave.impl_getdefault_multi(),
force=True)
def __setitem__(self, key, value): def __setitem__(self, key, value):
self._validate(value) self._validate(value)
@ -384,8 +391,9 @@ class Multi(list):
self.opt._validate(value) self.opt._validate(value)
except ValueError, err: except ValueError, err:
raise ValueError(_("invalid value {0} " raise ValueError(_("invalid value {0} "
"for option {1}: {2}").format(str(value), "for option {1}: {2}"
self.opt._name, err)) "").format(str(value),
self.opt._name, err))
def pop(self, key, force=False): def pop(self, key, force=False):
"""the list value can be updated (poped) """the list value can be updated (poped)
@ -403,7 +411,9 @@ class Multi(list):
values = self.context.cfgimpl_get_values() values = self.context.cfgimpl_get_values()
if not values.is_default_owner(slave): if not values.is_default_owner(slave):
#get multi without valid properties #get multi without valid properties
values.getitem(slave, validate_properties=False).pop(key, force=True) values.getitem(slave,
validate_properties=False
).pop(key, force=True)
#set value without valid properties #set value without valid properties
ret = super(Multi, self).pop(key) ret = super(Multi, self).pop(key)
self.context.cfgimpl_get_values()._setvalue(self.opt, self, validate_properties=not force) self.context.cfgimpl_get_values()._setvalue(self.opt, self, validate_properties=not force)