tiramisu/autolib.py: optimpl_ => impl_

tiramisu/option.py: consistency simplication and allow multi
tiramisu/option.py: don't touch cache if force_permissive or force_properties
tiramisu/values.py: set validate paramaters in Multi()
This commit is contained in:
Emmanuel Garette 2013-05-10 15:10:06 +02:00
parent 6ffd71a43e
commit fa5d643aee
4 changed files with 149 additions and 99 deletions

View file

@ -11,7 +11,7 @@ def test_consistency_not_equal():
a = IntOption('a', '') a = IntOption('a', '')
b = IntOption('b', '') b = IntOption('b', '')
od = OptionDescription('od', '', [a, b]) od = OptionDescription('od', '', [a, b])
a.impl_add_consistency('not_equal', (a, b)) a.impl_add_consistency('not_equal', b)
c = Config(od) c = Config(od)
assert c.a is None assert c.a is None
assert c.b is None assert c.b is None
@ -22,17 +22,32 @@ def test_consistency_not_equal():
c.b = 2 c.b = 2
def test_consistency_not_equal_multi():
a = IntOption('a', '', multi=True)
b = IntOption('b', '', multi=True)
od = OptionDescription('od', '', [a, b])
a.impl_add_consistency('not_equal', b)
c = Config(od)
assert c.a == []
assert c.b == []
c.a = [1]
del(c.a)
c.a = [1]
raises(ValueError, "c.b = [1]")
c.b = [2]
def test_consistency_default(): def test_consistency_default():
a = IntOption('a', '', 1) a = IntOption('a', '', 1)
b = IntOption('b', '', 1) b = IntOption('b', '', 1)
raises(ValueError, "a.impl_add_consistency('not_equal', (a, b))") raises(ValueError, "a.impl_add_consistency('not_equal', b)")
def test_consistency_default_diff(): def test_consistency_default_diff():
a = IntOption('a', '', 3) a = IntOption('a', '', 3)
b = IntOption('b', '', 1) b = IntOption('b', '', 1)
od = OptionDescription('od', '', [a, b]) od = OptionDescription('od', '', [a, b])
a.impl_add_consistency('not_equal', (a, b)) a.impl_add_consistency('not_equal', b)
c = Config(od) c = Config(od)
raises(ValueError, "c.a = 1") raises(ValueError, "c.a = 1")
c.a = 2 c.a = 2
@ -46,7 +61,7 @@ def test_consistency_ip_netmask():
a = IPOption('a', '') a = IPOption('a', '')
b = NetmaskOption('b', '') b = NetmaskOption('b', '')
od = OptionDescription('od', '', [a, b]) od = OptionDescription('od', '', [a, b])
b.impl_add_consistency('ip_netmask', (b, a)) b.impl_add_consistency('ip_netmask', a)
c = Config(od) c = Config(od)
c.a = '192.168.1.1' c.a = '192.168.1.1'
c.b = '255.255.255.0' c.b = '255.255.255.0'
@ -60,7 +75,7 @@ def test_consistency_network_netmask():
a = NetworkOption('a', '') a = NetworkOption('a', '')
b = NetmaskOption('b', '') b = NetmaskOption('b', '')
od = OptionDescription('od', '', [a, b]) od = OptionDescription('od', '', [a, b])
b.impl_add_consistency('network_netmask', (b, a)) b.impl_add_consistency('network_netmask', a)
c = Config(od) c = Config(od)
c.a = '192.168.1.1' c.a = '192.168.1.1'
c.b = '255.255.255.255' c.b = '255.255.255.255'
@ -68,3 +83,32 @@ def test_consistency_network_netmask():
c.a = '192.168.1.0' c.a = '192.168.1.0'
c.b = '255.255.255.0' c.b = '255.255.255.0'
raises(ValueError, "c.a = '192.168.1.1'") raises(ValueError, "c.a = '192.168.1.1'")
#FIXME pas de multi si pas de multi en maitre
def test_consistency_ip_netmask_multi():
a = IPOption('a', '', multi=True)
b = NetmaskOption('b', '', multi=True)
od = OptionDescription('od', '', [a, b])
b.impl_add_consistency('ip_netmask', a)
c = Config(od)
c.a = ['192.168.1.1']
c.b = ['255.255.255.0']
c.a = ['192.168.1.2']
c.b = ['255.255.255.255']
c.b = ['255.255.255.0']
raises(ValueError, "c.a = ['192.168.1.0']")
def test_consistency_network_netmask_multi():
a = NetworkOption('a', '', multi=True)
b = NetmaskOption('b', '', multi=True)
od = OptionDescription('od', '', [a, b])
b.impl_add_consistency('network_netmask', a)
c = Config(od)
c.a = ['192.168.1.1']
c.b = ['255.255.255.255']
del(c.b)
c.a = ['192.168.1.0']
c.b = ['255.255.255.0']
raises(ValueError, "c.a = ['192.168.1.1']")

View file

@ -56,7 +56,7 @@ def carry_out_calculation(name, config, callback, callback_params):
if check_disabled: if check_disabled:
continue continue
raise PropertiesOptionError(err, err.proptype) raise PropertiesOptionError(err, err.proptype)
is_multi = opt.optimpl_is_multi() is_multi = opt.impl_is_multi()
if is_multi: if is_multi:
if opt_value is not None: if opt_value is not None:
len_value = len(opt_value) len_value = len(opt_value)

View file

@ -189,8 +189,50 @@ class Option(BaseInformation):
return False return False
return not self == other return not self == other
def _launch_consistency(self, func, opt, value, context, index, opts): def _launch_consistency(self, func, opt, vals, context, index, opt_):
return getattr(self, func)(opt, value, context, index, opts) if context is not None:
descr = context.cfgimpl_get_description()
if opt is self:
#values are for self, search opt_ values
values = vals
if context is not None:
path = descr.impl_get_path_by_opt(opt_)
values_ = context._getattr(path, validate=False)
else:
values_ = opt_.impl_getdefault()
if index is not None:
#value is not already set, could be higher
try:
values_ = values_[index]
except IndexError:
values_ = None
else:
#values are for opt_, search self values
values_ = vals
if context is not None:
path = descr.impl_get_path_by_opt(self)
values = context._getattr(path, validate=False)
else:
values = self.impl_getdefault()
if index is not None:
#value is not already set, could be higher
try:
values = values[index]
except IndexError:
values = None
if index is None and self.impl_is_multi():
for index in range(0, len(values)):
try:
value = values[index]
value_ = values_[index]
except IndexError:
value = None
value_ = None
if None not in (value, value_):
getattr(self, func)(opt_._name, value, value_)
else:
if None not in (values, values_):
getattr(self, func)(opt_._name, values, values_)
def impl_validate(self, value, context=None, validate=True): def impl_validate(self, value, context=None, validate=True):
""" """
@ -282,38 +324,23 @@ class Option(BaseInformation):
def impl_is_multi(self): def impl_is_multi(self):
return self._multi return self._multi
def impl_add_consistency(self, func, opts): def impl_add_consistency(self, func, opt):
if self._consistencies is None: if self._consistencies is None:
self._consistencies = [] self._consistencies = []
if self not in opts: if not isinstance(opt, Option):
opts = list(opts) raise ValueError('consistency must be set with an option')
opts.append(self) if self is opt:
opts = tuple(opts) raise ValueError('cannot add consistency with itself')
func = '_cons_{}'.format(func) func = '_cons_{}'.format(func)
for opt in opts: self._launch_consistency(func, self, self.impl_getdefault(), None, None, opt)
if opt != self: self._consistencies.append((func, opt))
self._launch_consistency(func, opt, self.impl_getdefault(), None, None, opts)
self._consistencies.append((func, opts))
self.impl_validate(self.impl_getdefault(), None) self.impl_validate(self.impl_getdefault(), None)
def _cons_not_equal(self, opt, value, context, index, opts): def _cons_not_equal(self, optname, value, value_):
values = [value] if value == value_:
if context is not None: raise ValueError(_("invalid value {0} for option {1} "
descr = context.cfgimpl_get_description() "must be different as {2} option"
for opt_ in opts: "").format(value, self._name, optname))
if opt_ is not opt:
if context is not None:
path = descr.impl_get_path_by_opt(opt_)
val = context._getattr(path, validate=False)
else:
val = opt.impl_getdefault()
if val is not None:
if val in values:
raise ValueError(_("invalid value {0} for option {1} "
"must be different as {2} option"
"").format(val, self._name,
opt_._name))
values.append(val)
class ChoiceOption(Option): class ChoiceOption(Option):
@ -466,63 +493,42 @@ class NetmaskOption(Option):
except ValueError: except ValueError:
return False return False
def _cons_network_netmask(self, opt, value, context, index, opts): def _cons_network_netmask(self, optname, value, value_):
#opts must be (netmask, network) options #opts must be (netmask, network) options
self.__cons_netmask(opt, value, context, index, opts, False) self.__cons_netmask(optname, value, value_, False)
def _cons_ip_netmask(self, opt, value, context, index, opts): def _cons_ip_netmask(self, optname, value, value_):
#opts must be (netmask, ip) options #opts must be (netmask, ip) options
self.__cons_netmask(opt, value, context, index, opts, True) self.__cons_netmask(optname, value, value_, True)
def __cons_netmask(self, opt, value, context, index, opts, make_net): #def __cons_netmask(self, opt, value, context, index, opts, make_net):
opt_netmask, opt_ipnetwork = opts def __cons_netmask(self, optname, val_netmask, val_ipnetwork, make_net):
if context is not None: msg = None
descr = context.cfgimpl_get_description() try:
if opt is opt_ipnetwork: ip = IP('{0}/{1}'.format(val_ipnetwork, val_netmask),
val_ipnetwork = value make_net=make_net)
if context is not None: #if cidr == 32, ip same has network
path = descr.impl_get_path_by_opt(opt_netmask) if ip.prefixlen() != 32:
val_netmask = context._getattr(path, validate=False) try:
else: IP('{0}/{1}'.format(val_ipnetwork, val_netmask),
val_netmask = opt_netmask.impl_getdefault() make_net=not make_net)
if opt_netmask.impl_is_multi(): except ValueError:
val_netmask = val_netmask[index] if not make_net:
else: msg = _("invalid network {0} ({1}) with netmask {2} ({3}),"
val_netmask = value " this network is an ip")
if context is not None:
path = descr.impl_get_path_by_opt(opt_ipnetwork)
val_ipnetwork = context._getattr(path, validate=False)
else:
val_ipnetwork = opt_ipnetwork.impl_getdefault()
if opt_ipnetwork.impl_is_multi():
val_ipnetwork = val_ipnetwork[index]
if None not in (val_ipnetwork, val_netmask):
msg = None
try:
ip = IP('{0}/{1}'.format(val_ipnetwork, val_netmask),
make_net=make_net)
#if cidr == 32, ip same has network
if ip.prefixlen() != 32:
try:
IP('{0}/{1}'.format(val_ipnetwork, val_netmask),
make_net=not make_net)
except ValueError:
if not make_net:
msg = _("invalid network {0} ({1}) with netmask {2} ({3}),"
" this network is an ip")
else:
if make_net:
msg = _("invalid ip {0} ({1}) with netmask {2} ({3}),"
" this ip is a network")
except ValueError:
if make_net:
msg = _("invalid ip {0} ({1}) with netmask {2} ({3})")
else: else:
msg = _("invalid network {0} ({1}) with netmask {2} ({3})") if make_net:
if msg is not None: msg = _("invalid ip {0} ({1}) with netmask {2} ({3}),"
raise ValueError(msg.format(val_ipnetwork, opt_ipnetwork._name, " this ip is a network")
val_netmask, opt_netmask._name))
except ValueError:
if make_net:
msg = _("invalid ip {0} ({1}) with netmask {2} ({3})")
else:
msg = _("invalid network {0} ({1}) with netmask {2} ({3})")
if msg is not None:
raise ValueError(msg.format(val_ipnetwork, optname,
val_netmask, self._name))
class DomainnameOption(Option): class DomainnameOption(Option):
@ -674,9 +680,10 @@ class OptionDescription(BaseInformation):
if not isinstance(option, OptionDescription): if not isinstance(option, OptionDescription):
if option._consistencies is not None: if option._consistencies is not None:
for consistency in option._consistencies: for consistency in option._consistencies:
func, opts = consistency func, opt = consistency
for opt in opts: opts = (option, opt)
_consistencies.setdefault(opt, []).append((func, opts)) _consistencies.setdefault(opt, []).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)
@ -759,10 +766,9 @@ class OptionDescription(BaseInformation):
consistencies = self._consistencies.get(opt) consistencies = self._consistencies.get(opt)
if consistencies is not None: if consistencies is not None:
for consistency in consistencies: for consistency in consistencies:
func, opts = consistency opt_ = consistency[1]
#ret = getattr(opts[0], func)(opt, value, context, index, opts) ret = opt_[0]._launch_consistency(consistency[0], opt, value, context,
ret = opts[0]._launch_consistency(func, opt, value, context, index, opt_[1])
index, opts)
if ret is False: if ret is False:
return False return False
return True return True

View file

@ -99,7 +99,7 @@ class Values(object):
if exp < created: if exp < created:
return value return value
val = self._getitem(opt, validate, force_permissive, force_properties) val = self._getitem(opt, validate, force_permissive, force_properties)
if validate: if validate and force_permissive is False and force_properties is None:
self._set_cache(opt, val) self._set_cache(opt, val)
return val return val
@ -119,14 +119,14 @@ class Values(object):
else: else:
value = self._getcallback_value(opt) value = self._getcallback_value(opt)
if opt.impl_is_multi(): if opt.impl_is_multi():
value = Multi(value, self.context, opt) value = Multi(value, self.context, opt, validate)
#suppress value if already set #suppress value if already set
self._reset(opt) self._reset(opt)
# frozen and force default # frozen and force default
elif is_frozen and 'force_default_on_freeze' in setting[opt]: elif is_frozen and 'force_default_on_freeze' in setting[opt]:
value = self._get_default(opt) value = self._get_default(opt)
if opt.impl_is_multi(): if opt.impl_is_multi():
value = Multi(value, self.context, opt) value = Multi(value, self.context, opt, validate)
if validate: if validate:
opt.impl_validate(value, self.context, 'validator' in setting) opt.impl_validate(value, self.context, 'validator' in setting)
if self.is_default_owner(opt) and \ if self.is_default_owner(opt) and \
@ -209,7 +209,7 @@ class Multi(list):
that support item notation for the values of multi options""" that support item notation for the values of multi options"""
__slots__ = ('opt', 'context') __slots__ = ('opt', 'context')
def __init__(self, value, context, opt): def __init__(self, value, context, opt, validate=True):
""" """
:param value: the Multi wraps a list value :param value: the Multi wraps a list value
:param context: the home config that has the values :param context: the home config that has the values
@ -219,7 +219,7 @@ class Multi(list):
self.context = context self.context = context
if not isinstance(value, list): if not isinstance(value, list):
value = [value] value = [value]
if self.opt.impl_get_multitype() == multitypes.slave: if validate and self.opt.impl_get_multitype() == multitypes.slave:
value = self._valid_slave(value) value = self._valid_slave(value)
elif self.opt.impl_get_multitype() == multitypes.master: elif self.opt.impl_get_multitype() == multitypes.master:
self._valid_master(value) self._valid_master(value)