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

View File

@ -20,6 +20,8 @@
# the whole pypy projet is under MIT licence
# ____________________________________________________________
"user defined exceptions"
# Exceptions for an Option
class PropertiesOptionError(AttributeError):
"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
except AttributeError:
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):
"""retrieves one information's item
@ -81,10 +82,12 @@ class BaseInformation(object):
elif default is not None:
return default
else:
raise ValueError(_("Information's item not found: {0}").format(key))
raise ValueError(_("Information's item"
"not found: {0}").format(key))
except AttributeError:
raise AttributeError(_('{0} has no attribute '
'impl_get_information').format(self.__class__.__name__))
'impl_get_information').format(
self.__class__.__name__))
class Option(BaseInformation):
@ -93,8 +96,10 @@ class Option(BaseInformation):
Reminder: an Option object is **not** a container for the value
"""
__slots__ = ('_name', '_requires', '_multi', '_validator', '_default_multi',
'_default', '_properties', '_callback', '_multitype',
__slots__ = ('_name', '_requires', '_multi', '_validator',
'_default_multi',
'_default',
'_properties', '_callback', '_multitype',
'_master_slaves', '_consistencies', '_empty')
_empty = ''
@ -145,13 +150,16 @@ class Option(BaseInformation):
self._validate(default_multi)
except ValueError, err:
raise ValueError(_("invalid default_multi value {0} "
"for option {1}: {2}").format(str(default_multi), name, err))
if callback is not None and (default is not None or default_multi is not None):
"for option {1}: {2}").format(
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} "
"is calculated").format(name))
if callback is None and callback_params is not None:
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 type(callback) != FunctionType:
raise ValueError('callback must be a function')
@ -172,14 +180,18 @@ class Option(BaseInformation):
properties = tuple()
if not isinstance(properties, tuple):
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'...
def __eq__(self, other):
"Option comparison"
if not isinstance(other, Option):
return False
slots = list(self.__slots__ + Option.__slots__ + BaseInformation.__slots__)
slots = list(self.__slots__ +
Option.__slots__ +
BaseInformation.__slots__)
for var in slots:
try:
val1 = getattr(self, var)
@ -270,8 +282,11 @@ class Option(BaseInformation):
if _value is None:
return True
if not val_validator(_value):
raise ValueError(_("invalid value {0} for option {1} for object {2}"
"").format(_value, self._name, self.__class__.__name__))
raise ValueError(_("invalid value {0} "
"for option {1} for object {2}"
).format(_value,
self._name,
self.__class__.__name__))
try:
self._validate(_value)
except ValueError, err:
@ -314,7 +329,8 @@ class Option(BaseInformation):
def impl_is_empty_by_default(self):
"no default value has been set yet"
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 False
@ -343,9 +359,13 @@ class Option(BaseInformation):
if self is opt:
raise ValueError('cannot add consistency with itself')
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)
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.impl_validate(self.impl_getdefault())
@ -397,7 +417,8 @@ class ChoiceOption(Option):
def _validate(self, value):
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))
@ -462,7 +483,8 @@ class SymLinkOption(object):
self._name = name
if not isinstance(opt, Option):
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
def __getattr__(self, name):
@ -526,7 +548,10 @@ class PortOption(Option):
ports_min = [0, 1, 1024, 49152]
ports_max = [0, 1023, 49151, 65535]
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 allowed:
self._min_value = ports_min[index]
@ -556,7 +581,8 @@ class PortOption(Option):
if len(value) != 2:
raise ValueError('range must have two values only')
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:
value = [value]
@ -606,7 +632,8 @@ class NetmaskOption(Option):
make_net=not make_net)
except ValueError:
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")
else:
if make_net:
@ -672,7 +699,8 @@ class DomainnameOption(Option):
raise ValueError(_("invalid value for {0}, must have dot"
"").format(self._name))
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:
raise ValueError(_("invalid domainname's length for {0} (min 2)"
"").format(self._name))
@ -694,7 +722,8 @@ class OptionDescription(BaseInformation):
"""
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._impl_informations = {}
self.impl_set_information('doc', doc)
@ -717,7 +746,8 @@ class OptionDescription(BaseInformation):
properties = tuple()
if not isinstance(properties, tuple):
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'...
# the group_type is useful for filtering OptionDescriptions in a config
self._group_type = groups.default
@ -729,8 +759,9 @@ class OptionDescription(BaseInformation):
try:
return self._children[1][self._children[0].index(name)]
except ValueError:
raise AttributeError(_('unknown Option {0} in OptionDescription {1}'
'').format(name, self._name))
raise AttributeError(_('unknown Option {0} '
'in OptionDescription {1}'
'').format(name, self._name))
def impl_getkey(self, config):
return tuple([child.impl_getkey(getattr(config, child._name))
@ -757,7 +788,11 @@ class OptionDescription(BaseInformation):
def impl_getchildren(self):
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:
return
if _currpath is None:
@ -780,11 +815,16 @@ class OptionDescription(BaseInformation):
for consistency in option._consistencies:
func, opt = consistency
opts = (option, opt)
_consistencies.setdefault(opt, []).append((func, opts))
_consistencies.setdefault(option, []).append((func, opts))
_consistencies.setdefault(opt,
[]).append((func, opts))
_consistencies.setdefault(option,
[]).append((func, opts))
else:
_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()
if save:
#valid no duplicated option
@ -820,7 +860,8 @@ class OptionDescription(BaseInformation):
"""
if self._group_type != groups.default:
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):
self._group_type = group_type
if isinstance(group_type, groups.MasterGroupType):
@ -837,7 +878,8 @@ class OptionDescription(BaseInformation):
raise ValueError(_("master group {0} shall not have "
"a symlinkoption").format(self._name))
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"
"").format(child._name, self._name))
if child._name == self._name:
@ -847,18 +889,20 @@ class OptionDescription(BaseInformation):
else:
slaves.append(child)
if master is None:
raise ValueError(_('master group with wrong master name for {0}'
'').format(self._name))
raise ValueError(_('master group with wrong'
' master name for {0}'
).format(self._name))
master._master_slaves = tuple(slaves)
for child in self.impl_getchildren():
if child != master:
child._master_slaves = master
child._multitype = multitypes.slave
if not identical_master_child_name:
raise ValueError(_("no child has same nom has master group "
"for: {0}").format(self._name))
raise ValueError(_("no child has same nom has master group"
" for: {0}").format(self._name))
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):
return self._group_type
@ -868,8 +912,12 @@ class OptionDescription(BaseInformation):
if consistencies is not None:
for consistency in consistencies:
opt_ = consistency[1]
ret = opt_[0]._launch_consistency(consistency[0], opt, value, context,
index, opt_[1])
ret = opt_[0]._launch_consistency(consistency[0],
opt,
value,
context,
index,
opt_[1])
if ret is False:
return False
return True
@ -931,10 +979,12 @@ def validate_requires_arg(requires, name):
option._validate(expected)
except ValueError, err:
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 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))
else:
config_action[action] = inverse
@ -950,7 +1000,11 @@ def validate_requires_arg(requires, name):
for opt_requires in ret_requires.values():
ret_action = []
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.append(tuple(ret_action))
return tuple(ret)

View File

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

View File

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