This commit is contained in:
Emmanuel Garette 2018-09-12 21:05:14 +02:00
parent 10aaf2219f
commit cd7977eae6
13 changed files with 140 additions and 81 deletions

View file

@ -6,8 +6,9 @@ do_autopath()
from py.test import raises
from tiramisu.error import APIError
from tiramisu.error import APIError, ConfigError
from tiramisu import IntOption, OptionDescription, Config
from tiramisu.setting import groups
def a_func():
@ -113,6 +114,39 @@ def test_unknown_option():
raises(AttributeError, "api.option('od.unknown.suboption').value.get()")
def test_optiondescription_group():
groups.notfamily = groups.GroupType('notfamily')
i = IntOption('test', '')
i2 = IntOption('test', '')
od1 = OptionDescription('od', '', [i])
od1.impl_set_group_type(groups.family)
od3 = OptionDescription('od2', '', [i2])
od3.impl_set_group_type(groups.notfamily)
od2 = OptionDescription('od', '', [od1, od3])
api = Config(od2)
assert len(list(api.option.list('optiondescription'))) == 2
assert len(list(api.option.list('optiondescription', group_type=groups.family))) == 1
assert len(list(api.option.list('optiondescription', group_type=groups.notfamily))) == 1
def test_optiondescription_group_redefined():
try:
groups.notfamily = groups.GroupType('notfamily')
except:
pass
i = IntOption('test', '')
od1 = OptionDescription('od', '', [i])
od1.impl_set_group_type(groups.family)
raises(ValueError, "od1.impl_set_group_type(groups.notfamily)")
def test_optiondescription_group_masterslave():
i = IntOption('test', '')
od1 = OptionDescription('od', '', [i])
raises(ConfigError, "od1.impl_set_group_type(groups.master)")
def test_asign_optiondescription():
i = IntOption('test', '')
od1 = OptionDescription('od', '', [i])

View file

@ -241,6 +241,20 @@ def test_callback_params_without_callback():
raises(ValueError, "StrOption('val2', '', callback_params=Params(ParamValue('yes')))")
def test_params():
raises(ValueError, "Params([ParamContext()])")
raises(ValueError, "Params('str')")
raises(ValueError, "Params(('str',))")
raises(ValueError, "Params(kwargs=[ParamContext()])")
raises(ValueError, "Params(kwargs={'a': 'str'})")
def test_param_option():
val1 = StrOption('val1', "")
raises(ValueError, "ParamOption('str')")
raises(ValueError, "ParamOption(val1, 'str')")
def test_callback_invalid():
raises(ValueError, 'val1 = StrOption("val1", "", callback="string")')
raises(ValueError, 'val1 = StrOption("val1", "", callback=return_val, callback_params="string")')

View file

@ -415,6 +415,17 @@ def test_consistency_ip_netmask():
api.option('b').value.set('255.255.255.0')
raises(ValueError, "api.option('a').value.set('192.168.1.0')")
raises(ValueError, "api.option('a').value.set('192.168.1.255')")
api.option('a').value.reset()
api.option('b').value.reset()
api.option('a').value.set('192.168.1.255')
raises(ValueError, "api.option('b').value.set('255.255.255.0')")
def test_consistency_ip_netmask_invalid():
a = IPOption('a', '')
b = NetmaskOption('b', '')
od = OptionDescription('od', '', [a, b])
raises(ConfigError, "b.impl_add_consistency('ip_netmask')")
def test_consistency_network_netmask():
@ -431,6 +442,13 @@ def test_consistency_network_netmask():
raises(ValueError, "api.option('a').value.set('192.168.1.1')")
def test_consistency_network_netmask_invalid():
a = NetworkOption('a', '')
b = NetmaskOption('b', '')
od = OptionDescription('od', '', [a, b])
raises(ConfigError, "b.impl_add_consistency('network_netmask')")
def test_consistency_ip_in_network():
a = NetworkOption('a', '')
b = NetmaskOption('b', '')
@ -452,26 +470,13 @@ def test_consistency_ip_in_network():
assert len(w) == 1
# needs 3 arguments, not 2
#def test_consistency_ip_in_network_len_error():
# a = NetworkOption('a', '')
# b = NetmaskOption('b', '')
# c = IPOption('c', '')
# od = OptionDescription('od', '', [a, b, c])
# raises(ConfigError, "c.impl_add_consistency('in_network', a)")
# needs 2 arguments, not 3
#def test_consistency_ip_netmask_network_error():
# a = IPOption('a', '')
# b = NetworkOption('b', '')
# c = NetmaskOption('c', '')
# od = OptionDescription('od', '', [a, b, c])
# c.impl_add_consistency('ip_netmask', a, b)
# api = Config(od)
# api.option('a').value.set('192.168.1.1')
# api.option('b').value.set('192.168.1.0')
# raises(ConfigError, "api.option('c').value.set('255.255.255.0')")
def test_consistency_ip_in_network_invalid():
a = NetworkOption('a', '')
b = NetmaskOption('b', '')
c = IPOption('c', '')
d = IPOption('d', '')
od = OptionDescription('od', '', [a, b, c, d])
raises(ConfigError, "c.impl_add_consistency('in_network', a)")
def test_consistency_ip_netmask_error_multi():

View file

@ -112,6 +112,17 @@ def test_setowner_for_value():
assert api.option('dummy').owner.get() == owners.new2
def test_setowner_forbidden():
gcdummy = BoolOption('dummy', 'dummy', default=False)
descr = OptionDescription('tiramisu', '', [gcdummy])
api = Config(descr)
assert api.option('dummy').value.get() is False
assert api.option('dummy').owner.get() == 'default'
raises(ValueError, "api.owner.set('default')")
api.option('dummy').value.set(False)
raises(ValueError, "api.option('dummy').owner.set('default')")
def test_setowner_read_only():
gcdummy = BoolOption('dummy', 'dummy', default=False)
descr = OptionDescription('tiramisu', '', [gcdummy])

View file

@ -49,7 +49,8 @@ class BroadcastOption(Option):
current_opt,
opts,
vals,
warnings_only):
warnings_only,
context):
if len(vals) != 3:
raise ConfigError(_('invalid len for vals'))
if None in vals:

View file

@ -85,7 +85,6 @@ class ChoiceOption(Option):
current_opt=undefined):
if current_opt is undefined:
current_opt = self
#FIXME cache? but in context...
values = self._choice_values
if isinstance(values, FunctionType):
if option_bag is undefined:

View file

@ -101,7 +101,10 @@ class IPOption(Option):
current_opt,
opts,
vals,
warnings_only):
warnings_only,
context):
if len(vals) != 3 and context is undefined:
raise ConfigError(_('ip_network needs an IP, a network and a netmask'))
if len(vals) != 3 or None in vals:
return
ip, network, netmask = vals
@ -117,4 +120,5 @@ class IPOption(Option):
opts[2]._cons_ip_netmask(current_opt,
(opts[2], opts[0]),
(netmask, ip),
warnings_only)
warnings_only,
context)

View file

@ -50,9 +50,12 @@ class NetmaskOption(Option):
current_opt,
opts,
vals,
warnings_only):
warnings_only,
context):
#opts must be (netmask, network) options
if len(vals) != 2 or None in vals:
if context is undefined and len(vals) != 2:
raise ConfigError(_('network_netmask needs a network and a netmask'))
if None in vals or len(vals) != 2:
return
return self.__cons_netmask(current_opt,
opts,
@ -66,9 +69,12 @@ class NetmaskOption(Option):
current_opt,
opts,
vals,
warnings_only):
warnings_only,
context):
#opts must be (netmask, ip) options
if len(vals) != 2 or None in vals:
if context is undefined and len(vals) != 2:
raise ConfigError(_('ip_netmask needs an IP and a netmask'))
if None in vals or len(vals) != 2:
return
self.__cons_netmask(current_opt,
opts,
@ -86,8 +92,6 @@ class NetmaskOption(Option):
make_net,
warnings_only,
typ):
if len(opts) != 2:
raise ConfigError(_('invalid len for opts'))
msg = None
try:
ip = IP('{0}/{1}'.format(val_ipnetwork, val_netmask), make_net=make_net)
@ -99,7 +103,7 @@ class NetmaskOption(Option):
msg = _('this is a network with netmask "{0}" ("{1}")')
else:
msg = _('this is a network with {2} "{0}" ("{1}")')
if ip.broadcast() == val_ip:
elif ip.broadcast() == val_ip:
if current_opt == opts[1]:
msg = _('this is a broadcast with netmask "{0}" ("{1}")')
else:

View file

@ -207,8 +207,9 @@ class Option(OnlyOption):
return
def _is_not_unique(value):
#FIXME pourquoi la longueur doit etre egal ?
if check_error and self.impl_is_unique() and len(set(value)) != len(value):
# if set(value) has not same length than value
if check_error and self.impl_is_unique() and \
len(set(value)) != len(value):
for idx, val in enumerate(value):
if val in value[idx+1:]:
raise ValueError(_('invalid value "{}", this value is already in "{}"'
@ -243,7 +244,6 @@ class Option(OnlyOption):
if isinstance(_value, list): # pragma: no cover
raise ValueError(_('which must not be a list').format(_value,
self.impl_get_display_name()))
#FIXME a revoir ...
if _value is not None:
if check_error:
# option validation
@ -271,8 +271,6 @@ class Option(OnlyOption):
self.__class__.__name__, 0)
else:
raise err
#if is_multi is None:
# is_multi = self.impl_is_multi()
try:
val = value
if not self.impl_is_multi():
@ -332,8 +330,6 @@ class Option(OnlyOption):
return False
def impl_is_master_slaves(self, type_='both'):
"""FIXME
"""
master_slaves = self.impl_get_master_slaves()
if master_slaves is not None:
if type_ in ('both', 'master') and \
@ -654,7 +650,8 @@ class Option(OnlyOption):
getattr(self, func)(current_opt,
all_cons_opts,
values,
warnings_only)
warnings_only,
context)
except ValueError as err:
if warnings_only:
msg = _('attention, "{0}" could be an invalid {1} for "{2}", {3}'
@ -672,7 +669,8 @@ class Option(OnlyOption):
current_opt,
opts,
vals,
warnings_only):
warnings_only,
context):
equal = []
is_current = False
for idx_inf, val_inf in enumerate(vals):

View file

@ -74,6 +74,15 @@ class CacheOptionDescription(BaseOption):
if not option.impl_is_symlinkoption():
properties = option.impl_getproperties()
if 'force_store_value' in properties:
if option.impl_is_master_slaves('slave'):
# problem with index
raise ConfigError(_('the slave "{0}" cannot have '
'"force_store_value" property').format(
option.impl_get_display_name()))
if option.issubdyn():
raise ConfigError(_('the dynoption "{0}" cannot have '
'"force_store_value" property').format(
option.impl_get_display_name()))
force_store_values.append((subpath, option))
if 'force_default_on_freeze' in properties and \
'frozen' not in properties and \
@ -163,15 +172,6 @@ class CacheOptionDescription(BaseOption):
value_setted = False
values = context.cfgimpl_get_values()
for subpath, option in self._cache_force_store_values:
if option.impl_is_master_slaves('slave'):
# problem with index
raise ConfigError(_('the slave "{0}" cannot have '
'"force_store_value" property').format(
option.impl_get_display_name()))
if option.issubdyn():
raise ConfigError(_('the dynoption "{0}" cannot have '
'"force_store_value" property').format(
option.impl_get_display_name()))
if not values._p_.hasvalue(subpath):
config_bag = ConfigBag(context=context)
option_bag = OptionBag()
@ -429,12 +429,6 @@ class OptionDescription(OptionDescriptionWalk):
def impl_getdoc(self):
return self.impl_get_information('doc')
def impl_validate(self,
*args,
**kwargs):
"""usefull for OptionDescription"""
pass
# ____________________________________________________________
def impl_set_group_type(self,
group_type):
@ -444,8 +438,8 @@ class OptionDescription(OptionDescriptionWalk):
that lives in `setting.groups`
"""
if self._group_type != groups.default:
raise TypeError(_('cannot change group_type if already set '
'(old {0}, new {1})').format(self._group_type,
raise ValueError(_('cannot change group_type if already set '
'(old {0}, new {1})').format(self._group_type,
group_type))
if not isinstance(group_type, groups.GroupType):
raise ValueError(_('group_type: {0}'

View file

@ -785,6 +785,9 @@ class Settings(object):
def setowner(self,
owner):
":param owner: sets the default value for owner at the Config level"
if owner in forbidden_owners:
raise ValueError(_('set owner "{0}" is forbidden').format(str(owner)))
self._owner = owner
def getowner(self):

View file

@ -19,7 +19,7 @@ from time import time
from .cache.dictionary import Cache as DictCache
def _display_classname(obj):
def _display_classname(obj): # pragma: no cover
return(obj.__class__.__name__.lower())
DEBUG = False
@ -38,12 +38,12 @@ class Cache(DictCache):
if slave, add index
"""
if 'cache' in props or 'cache' in self_props:
if DEBUG:
if DEBUG: # pragma: no cover
print('setcache {} with index {} and value {} in {} ({})'.format(path, index, val,
_display_classname(self),
id(self)))
self._setcache(path, index, val, time())
elif DEBUG:
elif DEBUG: # pragma: no cover
print('not setcache {} with index {} and value {} and props {} and {} in {} ({})'.format(path,
index,
val,
@ -60,7 +60,7 @@ class Cache(DictCache):
self_props,
type_):
no_cache = False, None
if 'cache' in props:
if 'cache' in props or type_ == 'context_props':
indexed = self._getcache(path, index)
if indexed is None:
return no_cache
@ -79,22 +79,22 @@ class Cache(DictCache):
'expire' in self_props):
ntime = int(time())
if timestamp + expires_time >= ntime:
if DEBUG:
if DEBUG: # pragma: no cover
print('getcache in cache (1)', path, value, _display_classname(self),
id(self), index)
return True, value
else:
if DEBUG:
if DEBUG: # pragma: no cover
print('getcache expired value for path {} < {}'.format(
timestamp + expires_time, ntime))
# if expired, remove from cache
#self.delcache(path)
else:
if DEBUG:
if DEBUG: # pragma: no cover
print('getcache in cache (2)', path, value, _display_classname(self),
id(self), index)
return True, value
if DEBUG:
if DEBUG: # pragma: no cover
print('getcache {} with index {} not in {} cache'.format(path, index,
_display_classname(self)))
return no_cache
@ -102,14 +102,14 @@ class Cache(DictCache):
def delcache(self, path):
"""remove cache for a specified path
"""
if DEBUG:
if DEBUG: # pragma: no cover
print('delcache', path, _display_classname(self), id(self))
if path in self._cache:
self._delcache(path)
def reset_all_cache(self):
"empty the cache"
if DEBUG:
if DEBUG: # pragma: no cover
print('reset_all_cache', _display_classname(self), id(self))
self._reset_all_cache()
@ -118,6 +118,6 @@ class Cache(DictCache):
please only use it in test purpose
example: {'path1': {'index1': ('value1', 'time1')}, 'path2': {'index2': ('value2', 'time2', )}}
"""
if DEBUG:
if DEBUG: # pragma: no cover
print('get_chached {} for {} ({})'.format(self._cache, _display_classname(self), id(self)))
return self._get_cached()

View file

@ -109,19 +109,11 @@ class Values(object):
owners.default,
index=_index,
with_value=True)
if owner != owners.default:
if owner != owners.default and not ('frozen' in option_bag.properties and \
'force_default_on_freeze' in option_bag.properties):
# if a value is store in storage, check if not frozen + force_default_on_freeze
# if frozen + force_default_on_freeze => force default value
if not ('frozen' in option_bag.properties and \
'force_default_on_freeze' in option_bag.properties):
if index is not None and not is_slave:
if len(value) > index:
return value[index]
#value is smaller than expected
#so return default value
else:
return value
return value
return self.getdefaultvalue(option_bag)
def getdefaultvalue(self,
@ -415,7 +407,7 @@ class Values(object):
raise ConfigError(_("can't set owner for the symlinkoption \"{}\""
"").format(opt.impl_get_display_name()))
if owner in forbidden_owners:
raise ConfigError(_('set owner "{0}" is forbidden').format(str(owner)))
raise ValueError(_('set owner "{0}" is forbidden').format(str(owner)))
if not self._p_.hasvalue(option_bag.path):
raise ConfigError(_('no value for {0} cannot change owner to {1}'