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', '')
b = IntOption('b', '')
od = OptionDescription('od', '', [a, b])
a.impl_add_consistency('not_equal', (a, b))
a.impl_add_consistency('not_equal', b)
c = Config(od)
assert c.a is None
assert c.b is None
@ -22,17 +22,32 @@ def test_consistency_not_equal():
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():
a = IntOption('a', '', 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():
a = IntOption('a', '', 3)
b = IntOption('b', '', 1)
od = OptionDescription('od', '', [a, b])
a.impl_add_consistency('not_equal', (a, b))
a.impl_add_consistency('not_equal', b)
c = Config(od)
raises(ValueError, "c.a = 1")
c.a = 2
@ -46,7 +61,7 @@ def test_consistency_ip_netmask():
a = IPOption('a', '')
b = NetmaskOption('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.a = '192.168.1.1'
c.b = '255.255.255.0'
@ -60,7 +75,7 @@ def test_consistency_network_netmask():
a = NetworkOption('a', '')
b = NetmaskOption('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.a = '192.168.1.1'
c.b = '255.255.255.255'
@ -68,3 +83,32 @@ def test_consistency_network_netmask():
c.a = '192.168.1.0'
c.b = '255.255.255.0'
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:
continue
raise PropertiesOptionError(err, err.proptype)
is_multi = opt.optimpl_is_multi()
is_multi = opt.impl_is_multi()
if is_multi:
if opt_value is not None:
len_value = len(opt_value)

View File

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

View File

@ -99,7 +99,7 @@ class Values(object):
if exp < created:
return value
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)
return val
@ -119,14 +119,14 @@ class Values(object):
else:
value = self._getcallback_value(opt)
if opt.impl_is_multi():
value = Multi(value, self.context, opt)
value = Multi(value, self.context, opt, validate)
#suppress value if already set
self._reset(opt)
# frozen and force default
elif is_frozen and 'force_default_on_freeze' in setting[opt]:
value = self._get_default(opt)
if opt.impl_is_multi():
value = Multi(value, self.context, opt)
value = Multi(value, self.context, opt, validate)
if validate:
opt.impl_validate(value, self.context, 'validator' in setting)
if self.is_default_owner(opt) and \
@ -209,7 +209,7 @@ class Multi(list):
that support item notation for the values of multi options"""
__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 context: the home config that has the values
@ -219,7 +219,7 @@ class Multi(list):
self.context = context
if not isinstance(value, list):
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)
elif self.opt.impl_get_multitype() == multitypes.master:
self._valid_master(value)