requires could be apply to a slave and properties could be different

This commit is contained in:
Emmanuel Garette 2015-11-29 23:03:08 +01:00
parent c2a6772ec2
commit a521a6d322
20 changed files with 403 additions and 241 deletions

View File

@ -1,3 +1,6 @@
Sun Nov 29 23:01:28 2015 +0200 Emmanuel Garette <egarette@cadoles.com>
* requires could be apply to a slave and properties could be different
Mon Oct 12 17:05:28 2015 +0200 Emmanuel Garette <egarette@cadoles.com>
* domainname with only one character is now allowed

View File

@ -4,9 +4,10 @@ do_autopath()
from tiramisu import setting
setting.expires_time = 1
from tiramisu.option import IntOption, OptionDescription
from tiramisu.option import IntOption, StrOption, OptionDescription
from tiramisu.config import Config
from tiramisu.error import ConfigError, PropertiesOptionError
from tiramisu.error import ConfigError
from tiramisu.setting import groups
from time import sleep, time
@ -50,9 +51,9 @@ def test_get_cache():
values = c.cfgimpl_get_values()
settings = c.cfgimpl_get_settings()
ntime = time() + 1
settings._p_.setcache('u1', set(['inject']), ntime)
settings._p_.setcache('u1', set(['inject']), ntime, None)
assert 'inject' in settings[od1.u1]
values._p_.setcache('u1', 100, ntime)
values._p_.setcache('u1', 100, ntime, None)
assert c.u1 == [100]
@ -62,9 +63,9 @@ def test_get_cache_no_expire():
c = Config(od1)
values = c.cfgimpl_get_values()
settings = c.cfgimpl_get_settings()
settings._p_.setcache('u1', set(['inject2']), None)
settings._p_.setcache('u1', set(['inject2']), None, None)
assert 'inject2' in settings[od1.u1]
values._p_.setcache('u1', 200, None)
values._p_.setcache('u1', 200, None, None)
assert c.u1 == [200]
@ -279,13 +280,70 @@ def test_force_cache():
c.cfgimpl_get_settings().remove('expire')
c.cfgimpl_get_values().force_cache()
assert c.cfgimpl_get_values()._p_.get_cached(c) == {'u1': ([], None), 'u3': ([], None), 'u2': (None, None), 'u4': (None, None)}
assert c.cfgimpl_get_settings()._p_.get_cached(c) == {'u4': (set(['disabled']), None), 'u1': (set([]), None), 'u3': (set([]), None), 'u2': (set([]), None)}
assert c.cfgimpl_get_values()._p_.get_cached(c) == {'u1': {None: ([], None)},
'u2': {None: (None, None)},
'u3': {None: ([], None)},
'u4': {None: (None, None)}}
assert c.cfgimpl_get_settings()._p_.get_cached(c) == {'u1': {None: (set([]), None)},
'u2': {None: (set([]), None)},
'u3': {None: (set([]), None)},
'u4': {None: (set(['disabled']), None)}}
c.read_only()
c.cfgimpl_get_values().force_cache()
assert c.cfgimpl_get_values()._p_.get_cached(c) == {'u1': ([], None), 'u3': ([], None), 'u2': (None, None)}
assert c.cfgimpl_get_settings()._p_.get_cached(c) == {'u4': (set(['disabled']), None), 'u1': (set([]), None), 'u3': (set([]), None), 'u2': (set([]), None)}
assert c.cfgimpl_get_values()._p_.get_cached(c) == {'u1': {None: ([], None)},
'u2': {None: (None, None)},
'u3': {None: ([], None)}}
assert c.cfgimpl_get_settings()._p_.get_cached(c) == {'u1': {None: (set([]), None)},
'u2': {None: (set([]), None)},
'u3': {None: (set([]), None)},
'u4': {None: (set(['disabled']), None)}}
c.cfgimpl_get_settings().remove('cache')
raises(ConfigError, "c.cfgimpl_get_values().force_cache()")
def test_cache_master_slave():
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True)
interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
interface1.impl_set_group_type(groups.master)
maconfig = OptionDescription('toto', '', [interface1])
cfg = Config(maconfig)
cfg.read_write()
assert cfg.cfgimpl_get_values()._p_.get_cached(cfg) == {}
assert cfg.cfgimpl_get_settings()._p_.get_cached(cfg) == {}
#
cfg.ip_admin_eth0.ip_admin_eth0.append('192.168.1.2')
cfg.ip_admin_eth0.ip_admin_eth0
cfg.ip_admin_eth0.netmask_admin_eth0
cache = cfg.cfgimpl_get_values()._p_.get_cached(cfg)
assert set(cache.keys()) == set(['ip_admin_eth0.ip_admin_eth0', 'ip_admin_eth0.netmask_admin_eth0'])
assert set(cache['ip_admin_eth0.ip_admin_eth0'].keys()) == set([None])
assert cache['ip_admin_eth0.ip_admin_eth0'][None][0] == ['192.168.1.2']
assert set(cache['ip_admin_eth0.netmask_admin_eth0'].keys()) == set([None, 0])
assert cache['ip_admin_eth0.netmask_admin_eth0'][None][0] == [None]
assert cache['ip_admin_eth0.netmask_admin_eth0'][0][0] is None
cache = cfg.cfgimpl_get_settings()._p_.get_cached(cfg)
assert set(cache.keys()) == set(['ip_admin_eth0', 'ip_admin_eth0.ip_admin_eth0', 'ip_admin_eth0.netmask_admin_eth0'])
assert set(cache['ip_admin_eth0'].keys()) == set([None])
assert set(cache['ip_admin_eth0.ip_admin_eth0'].keys()) == set([None])
assert set(cache['ip_admin_eth0.netmask_admin_eth0'].keys()) == set([None, 0])
#
cfg.ip_admin_eth0.ip_admin_eth0.append('192.168.1.1')
cfg.ip_admin_eth0.ip_admin_eth0
cfg.ip_admin_eth0.netmask_admin_eth0
cache = cfg.cfgimpl_get_values()._p_.get_cached(cfg)
assert set(cache.keys()) == set(['ip_admin_eth0.ip_admin_eth0', 'ip_admin_eth0.netmask_admin_eth0'])
assert set(cache['ip_admin_eth0.ip_admin_eth0'].keys()) == set([None])
assert cache['ip_admin_eth0.ip_admin_eth0'][None][0] == ['192.168.1.2', '192.168.1.1']
assert set(cache['ip_admin_eth0.netmask_admin_eth0'].keys()) == set([None, 0, 1])
assert cache['ip_admin_eth0.netmask_admin_eth0'][None][0] == [None, None]
assert cache['ip_admin_eth0.netmask_admin_eth0'][0][0] is None
assert cache['ip_admin_eth0.netmask_admin_eth0'][1][0] is None
cache = cfg.cfgimpl_get_settings()._p_.get_cached(cfg)
assert set(cache.keys()) == set(['ip_admin_eth0', 'ip_admin_eth0.ip_admin_eth0', 'ip_admin_eth0.netmask_admin_eth0'])
assert set(cache['ip_admin_eth0'].keys()) == set([None])
assert set(cache['ip_admin_eth0.ip_admin_eth0'].keys()) == set([None])
assert set(cache['ip_admin_eth0.netmask_admin_eth0'].keys()) == set([None, 0, 1])
#DEL, insert, ...

View File

@ -102,6 +102,24 @@ def test_make_dict_with_disabled():
OptionDescription("s1", "", [
BoolOption("a", "", default=False),
BoolOption("b", "", default=False, properties=('disabled',))]),
OptionDescription("s2", "", [
BoolOption("a", "", default=False),
BoolOption("b", "", default=False)], properties=('disabled',)),
IntOption("int", "", default=42)])
config = Config(descr)
config.read_only()
d = config.make_dict()
assert d == {"s1.a": False, "int": 42}
def test_make_dict_with_disabled_in_callback():
descr = OptionDescription("opt", "", [
OptionDescription("s1", "", [
BoolOption("a", "", default=False),
BoolOption("b", "", default=False, properties=('disabled',))]),
OptionDescription("s2", "", [
BoolOption("a", "", default=False),
BoolOption("b", "", default=False)], properties=('disabled',)),
IntOption("int", "", default=42)])
config = Config(descr)
config.read_only()

View File

@ -4,7 +4,7 @@ do_autopath()
from py.test import raises
from tiramisu.setting import owners
from tiramisu.setting import owners, groups
from tiramisu.config import Config
from tiramisu.option import ChoiceOption, BoolOption, IntOption, FloatOption, \
StrOption, OptionDescription
@ -96,6 +96,7 @@ def test_default_with_multi():
def test_idontexist():
descr = make_description()
cfg = Config(descr)
cfg
raises(AttributeError, "cfg.idontexist")
@ -222,9 +223,50 @@ def test_multi_with_requires_with_disabled_in_another_group():
def test_multi_with_requires_that_is_multi():
s = StrOption("string", "", default=["string"], multi=True)
intoption = IntOption('int', 'Test int option', default=[0], multi=True)
raises(ValueError, "StrOption('str', 'Test string option', default=['abc'], requires=[{'option': intoption, 'expected': 1, 'action': 'hidden'}], multi=True)")
b = IntOption('int', 'Test int option', default=[0], multi=True)
c = StrOption('str', 'Test string option', default=['abc'], requires=[{'option': b, 'expected': 1, 'action': 'hidden'}], multi=True)
descr = OptionDescription("opt", "", [b, c])
descr
raises(ValueError, "Config(descr)")
def test_multi_with_requires_that_is_masterslave():
b = IntOption('int', 'Test int option', default=[0], multi=True)
c = StrOption('str', 'Test string option', requires=[{'option': b, 'expected': 1, 'action': 'hidden'}], multi=True)
descr = OptionDescription("int", "", [b, c])
descr.impl_set_group_type(groups.master)
Config(descr)
def test_multi_with_requires_that_is_masterslave_master():
b = IntOption('int', 'Test int option', multi=True)
c = StrOption('str', 'Test string option', requires=[{'option': b, 'expected': 1, 'action': 'hidden'}], multi=True)
descr = OptionDescription("str", "", [c, b])
descr.impl_set_group_type(groups.master)
raises(ValueError, "Config(descr)")
def test_multi_with_requires_that_is_masterslave2():
b = IntOption('int', 'Test int option', default=[0], multi=True)
c = StrOption('str', 'Test string option', multi=True)
d = StrOption('str1', 'Test string option', requires=[{'option': c, 'expected': '1', 'action': 'hidden'}], multi=True)
descr = OptionDescription("int", "", [b, c, d])
descr.impl_set_group_type(groups.master)
Config(descr)
def test_multi_with_requires_that_is_not_same_masterslave():
b = IntOption('int', 'Test int option', default=[0], multi=True)
c = StrOption('str', 'Test string option', requires=[{'option': b, 'expected': 1, 'action': 'hidden'}], multi=True)
descr1 = OptionDescription("int", "", [b, c])
descr1.impl_set_group_type(groups.master)
d = IntOption('int1', 'Test int option', default=[0], multi=True)
e = StrOption('str', 'Test string option', requires=[{'option': b, 'expected': 1, 'action': 'hidden'}], multi=True)
descr2 = OptionDescription("int1", "", [d, e])
descr2.impl_set_group_type(groups.master)
descr3 = OptionDescription('val', '', [descr1, descr2])
descr3
raises(ValueError, "Config(descr3)")
def test_multi_with_bool():
@ -241,6 +283,7 @@ def test_multi_with_bool_two():
s = BoolOption("bool", "", default=[False], multi=True)
descr = OptionDescription("options", "", [s])
config = Config(descr)
config
assert descr.bool.impl_is_multi() is True
raises(ValueError, "config.bool = True")
@ -383,5 +426,6 @@ def test_properties_cached():
c.read_write()
setting = c.cfgimpl_get_settings()
option = c.cfgimpl_get_description().sub.b1
option
c._setattr('sub.b1', True, force_permissive=True)
assert str(setting[b1]) in ["['test']", "[u'test']"]

View File

@ -242,6 +242,7 @@ def test_allowed_groups():
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True)
interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
interface1
raises(ValueError, "interface1.impl_set_group_type('toto')")
@ -266,6 +267,7 @@ def test_master_not_valid_name():
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True)
invalid_group = OptionDescription('interface1', '', [ip_admin_eth0, netmask_admin_eth0])
invalid_group
raises(ValueError, "invalid_group.impl_set_group_type(groups.master)")
@ -274,6 +276,7 @@ def test_sub_group_in_master_group():
netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True)
subgroup = OptionDescription("subgroup", '', [])
invalid_group = OptionDescription('ip_admin_eth0', '', [subgroup, ip_admin_eth0, netmask_admin_eth0])
invalid_group
raises(ValueError, "invalid_group.impl_set_group_type(groups.master)")
@ -281,6 +284,7 @@ def test_group_always_has_multis():
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau")
group = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
group
raises(ValueError, "group.impl_set_group_type(groups.master)")

View File

@ -3,6 +3,7 @@ from autopath import do_autopath
do_autopath()
from copy import copy
from tiramisu.setting import groups
from tiramisu import setting
setting.expires_time = 1
from tiramisu.option import IPOption, OptionDescription, BoolOption, IntOption, StrOption
@ -52,6 +53,7 @@ def test_requires_with_requires():
def test_requires_invalid():
a = BoolOption('activate_service', '', True)
a
raises(ValueError, "IPOption('ip_address_service', '', requires='string')")
raises(ValueError, "IPOption('ip_address_service', '', requires=[{'option': a, 'expected': False, 'action': 'disabled', 'unknown': True}])")
raises(ValueError, "IPOption('ip_address_service', '', requires=[{'option': a, 'expected': False}])")
@ -568,6 +570,7 @@ def test_requires_requirement_append():
def test_requires_different_inverse():
a = BoolOption('activate_service', '', True)
a
raises(ValueError, "IPOption('ip_address_service', '', requires=[{'option': a, 'expected': True, 'action': 'disabled', 'inverse': True}, {'option': a, 'expected': True, 'action': 'disabled', 'inverse': False}])")
@ -605,5 +608,25 @@ def test_set_item():
def test_properties_conflict():
a = BoolOption('activate_service', '', True)
a
raises(ValueError, "IPOption('ip_address_service', '', properties=('disabled',), requires=[{'option': a, 'expected': False, 'action': 'disabled'}])")
raises(ValueError, "od1 = OptionDescription('service', '', [a], properties=('disabled',), requires=[{'option': a, 'expected': False, 'action': 'disabled'}])")
def test_master_slave_requires():
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True,
requires=[{'option': ip_admin_eth0, 'expected': '192.168.1.1', 'action': 'disabled'}])
interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
interface1.impl_set_group_type(groups.master)
maconfig = OptionDescription('toto', '', [interface1])
cfg = Config(maconfig)
cfg.read_write()
assert cfg.ip_admin_eth0.netmask_admin_eth0 == []
assert cfg.ip_admin_eth0.ip_admin_eth0 == []
cfg.ip_admin_eth0.ip_admin_eth0.append('192.168.1.2')
assert cfg.ip_admin_eth0.netmask_admin_eth0 == [None]
assert cfg.ip_admin_eth0.ip_admin_eth0 == ['192.168.1.2']
cfg.ip_admin_eth0.ip_admin_eth0.append('192.168.1.1')
assert cfg.ip_admin_eth0.netmask_admin_eth0[0] is None
raises(PropertiesOptionError, "cfg.ip_admin_eth0.netmask_admin_eth0[1]")

View File

@ -62,21 +62,21 @@ def test_slots_option_readonly():
p = URLOption('p', '')
q = FilenameOption('q', '')
m = OptionDescription('m', '', [a, b, c, d, e, g, h, i, j, k, l, o, p, q])
a._requires = 'a'
b._requires = 'b'
c._requires = 'c'
d._requires = 'd'
e._requires = 'e'
g._requires = 'g'
h._requires = 'h'
i._requires = 'i'
j._requires = 'j'
k._requires = 'k'
l._requires = 'l'
m._requires = 'm'
o._requires = 'o'
p._requires = 'p'
q._requires = 'q'
a._requires = (((a,),),)
b._requires = (((a,),),)
c._requires = (((a,),),)
d._requires = (((a,),),)
e._requires = (((a,),),)
g._requires = (((a,),),)
h._requires = (((a,),),)
i._requires = (((a,),),)
j._requires = (((a,),),)
k._requires = (((a,),),)
l._requires = (((a,),),)
m._requires = (((a,),),)
o._requires = (((a,),),)
p._requires = (((a,),),)
q._requires = (((a,),),)
Config(m)
raises(AttributeError, "a._requires = 'a'")
raises(AttributeError, "b._requires = 'b'")

View File

@ -18,10 +18,10 @@
# the whole pypy projet is under MIT licence
# ____________________________________________________________
"enables us to carry out a calculation and return an option's value"
from tiramisu.error import PropertiesOptionError, ConfigError, ContextError, \
from .error import PropertiesOptionError, ConfigError, ContextError, \
SlaveError
from tiramisu.i18n import _
from tiramisu.setting import undefined
from .i18n import _
from .setting import undefined
# ____________________________________________________________
@ -222,9 +222,13 @@ def carry_out_calculation(option, context, callback, callback_params,
else:
kwargs[key] = couple[0]
ret = calculate(callback, args, kwargs)
if callback_params != {} and isinstance(ret, list) and index is not undefined:
raise SlaveError(_("callback cannot return a list for a "
"slave option ({0})").format(path))
try:
if callback_params != {} and isinstance(ret, list) and \
option.impl_is_master_slaves('slave'):
raise SlaveError(_("callback cannot return a list for a "
"slave option ({0})").format(path))
except AttributeError:
pass
return ret

View File

@ -22,15 +22,15 @@
import weakref
from tiramisu.error import PropertiesOptionError, ConfigError, ConflictError
from tiramisu.option import OptionDescription, Option, SymLinkOption, \
from .error import PropertiesOptionError, ConfigError, ConflictError
from .option import OptionDescription, Option, SymLinkOption, \
DynSymLinkOption
from tiramisu.option.baseoption import valid_name
from tiramisu.setting import groups, Settings, default_encoding, undefined
from tiramisu.storage import get_storages, get_storage, set_storage, \
from .option.baseoption import valid_name
from .setting import groups, Settings, default_encoding, undefined
from .storage import get_storages, get_storage, set_storage, \
_impl_getstate_setting, get_storages_validation
from tiramisu.value import Values, Multi
from tiramisu.i18n import _
from .value import Values, Multi
from .i18n import _
class SubConfig(object):
@ -242,7 +242,7 @@ class SubConfig(object):
return subpath
def getattr(self, name, force_permissive=False, validate=True,
_setting_properties=undefined):
_setting_properties=undefined, index=None):
"""
attribute notation mechanism for accessing the value of an option
:param name: attribute name
@ -256,23 +256,25 @@ class SubConfig(object):
name, force_permissive=force_permissive)
return homeconfig.getattr(name, force_permissive=force_permissive,
validate=validate,
_setting_properties=_setting_properties)
_setting_properties=_setting_properties,
index=index)
context = self._cfgimpl_get_context()
option = self.cfgimpl_get_description().__getattr__(name,
context=context)
subpath = self._get_subpath(name)
if isinstance(option, DynSymLinkOption):
return self.cfgimpl_get_values()._get_cached_item(
return self.cfgimpl_get_values()._get_cached_value(
option, path=subpath,
validate=validate,
force_permissive=force_permissive,
setting_properties=_setting_properties)
setting_properties=_setting_properties, index=index)
elif isinstance(option, SymLinkOption): # pragma: no dynoptiondescription cover
path = context.cfgimpl_get_description().impl_get_path_by_opt(
option._impl_getopt())
return context.getattr(path, validate=validate,
force_permissive=force_permissive,
_setting_properties=_setting_properties)
_setting_properties=_setting_properties,
index=index)
elif option.impl_is_optiondescription():
self.cfgimpl_get_settings().validate_properties(
option, True, False, path=subpath,
@ -280,11 +282,12 @@ class SubConfig(object):
setting_properties=_setting_properties)
return SubConfig(option, self._impl_context, subpath)
else:
return self.cfgimpl_get_values()._get_cached_item(
return self.cfgimpl_get_values()._get_cached_value(
option, path=subpath,
validate=validate,
force_permissive=force_permissive,
setting_properties=_setting_properties)
setting_properties=_setting_properties,
index=index)
def find(self, bytype=None, byname=None, byvalue=undefined, type_='option',
check_properties=True, force_permissive=False):

View File

@ -22,12 +22,12 @@ import re
from types import FunctionType
import warnings
from tiramisu.i18n import _
from tiramisu.setting import log, undefined
from tiramisu.autolib import carry_out_calculation
from tiramisu.error import ConfigError, ValueWarning, PropertiesOptionError,\
from ..i18n import _
from ..setting import log, undefined
from ..autolib import carry_out_calculation
from ..error import ConfigError, ValueWarning, PropertiesOptionError,\
ContextError
from tiramisu.storage import get_storages_option
from ..storage import get_storages_option
StorageBase = get_storages_option('base')
@ -853,10 +853,6 @@ def validate_requires_arg(requires, name):
if not isinstance(option, Option): # pragma: optional cover
raise ValueError(_('malformed requirements '
'must be an option in option {0}').format(name))
if option.impl_is_multi(): # pragma: optional cover
raise ValueError(_('malformed requirements option {0} '
'must not be a multi for {1}').format(
option.impl_getname(), name))
if expected is not None:
try:
option._validate(expected)

View File

@ -19,9 +19,9 @@
# the rough pypy's guys: http://codespeak.net/svn/pypy/dist/pypy/config/
# the whole pypy projet is under MIT licence
# ____________________________________________________________
from tiramisu.i18n import _
from tiramisu.setting import log, undefined
from tiramisu.error import SlaveError, ConfigError
from ..i18n import _
from ..setting import log, undefined
from ..error import SlaveError, ConfigError, PropertiesOptionError
from .baseoption import DynSymLinkOption, SymLinkOption, Option
@ -50,8 +50,8 @@ class MasterSlaves(object):
else:
if child.impl_getdefault() != []:
raise ValueError(_("not allowed default value for option {0} "
"in group {1}").format(child.impl_getname(),
name))
"in group {1}").format(child.impl_getname(),
name))
slaves.append(child)
if self.master is None: # pragma: optional cover
raise ValueError(_('master group with wrong'
@ -112,50 +112,41 @@ class MasterSlaves(object):
for slave in self.getslaves(opt):
if not values.is_default_owner(slave, validate_properties=False,
validate_meta=False, index=index):
values._get_cached_item(slave, validate=False,
validate_properties=False
).pop(index, force=True)
values._get_cached_value(slave, validate=False,
validate_properties=False
).pop(index, force=True)
pass
def getitem(self, values, opt, path, validate, force_permissive,
force_properties, validate_properties, slave_path=undefined,
slave_value=undefined, setting_properties=undefined, self_properties=undefined):
slave_value=undefined, setting_properties=undefined,
self_properties=undefined, index=None):
if self.is_master(opt):
return self._getmaster(values, opt, path, validate,
force_permissive, force_properties,
validate_properties, slave_path,
slave_value, self_properties)
slave_value, self_properties, index)
else:
return self._getslave(values, opt, path, validate,
force_permissive, force_properties,
validate_properties, setting_properties, self_properties)
validate_properties, setting_properties,
self_properties, index)
def _getmaster(self, values, opt, path, validate, force_permissive,
force_properties, validate_properties, c_slave_path,
c_slave_value, self_properties):
c_slave_value, self_properties, index):
value = values._get_validated_value(opt, path, validate,
force_permissive,
force_properties,
validate_properties,
self_properties=self_properties)
if validate is True:
self_properties=self_properties,
index=index)
if index is None and validate is True:
masterlen = len(value)
for slave in self.getslaves(opt):
try:
slave_path = slave.impl_getpath(values._getcontext())
slavelen = values._p_.get_max_length(slave_path)
#if c_slave_path == slave_path:
# slave_value = c_slave_value
#else:
# slave_value = values._get_validated_value(slave,
# slave_path,
# False,
# False,
# None, False,
# None,
# self_properties=self_properties,
# masterlen=masterlen)
#slavelen = len(slave_value)
self.validate_slave_length(masterlen, slavelen, slave.impl_getname(), opt)
except ConfigError: # pragma: optional cover
pass
@ -163,7 +154,7 @@ class MasterSlaves(object):
def _getslave(self, values, opt, path, validate, force_permissive,
force_properties, validate_properties, setting_properties,
self_properties):
self_properties, index):
"""
if master has length 0:
return []
@ -191,46 +182,43 @@ class MasterSlaves(object):
masterlen = self.get_length(values, opt, validate, undefined,
undefined, force_permissive,
master=master)
master_is_meta = values._is_meta(opt, masterp)
#value = values._get_validated_value(opt, path, validate,
# force_permissive,
# force_properties,
# validate_properties,
# None, # not undefined
# with_meta=master_is_meta,
# self_properties=self_properties)
#if slave, had values until master's one
#path = opt.impl_getpath(context)
#valuelen = len(value)
#if validate:
# self.validate_slave_length(masterlen, valuelen,
# opt.impl_getname(), opt)
#if valuelen < masterlen:
#FIXME voir si pas de plus grande valeur !
value = values._get_multi(opt, path)
for index in range(0, masterlen):
#index = valuelen + num
value.append(values._get_validated_value(opt, path, validate,
master_is_meta = values._is_meta(master, masterp)
multi = values._get_multi(opt, path)
if masterlen == 0:
if validate_properties:
context.cfgimpl_get_settings().validate_properties(opt, False,
False,
value=multi,
path=path,
force_permissive=force_permissive,
force_properties=force_properties,
setting_properties=setting_properties)
else:
one_has_value = False
if index is None:
indexes = range(0, masterlen)
else:
indexes = [index]
for idx in indexes:
try:
value = values._get_cached_value(opt, path, validate,
force_permissive, force_properties,
validate_properties,
with_meta=master_is_meta,
index=index,
self_properties=self_properties,
masterlen=masterlen),
setitem=False,
force=True,
validate=validate)
#FIXME hu?
if validate_properties:
context.cfgimpl_get_settings().validate_properties(opt, False,
False,
value=value,
path=path,
force_permissive=force_permissive,
force_properties=force_properties,
setting_properties=setting_properties)
return value
index=idx,
# not self_properties,
# depends to index
#self_properties=self_properties,
masterlen=masterlen,
from_masterslave=True)
multi.append(value, setitem=False, force=True, validate=validate)
one_has_value = True
except PropertiesOptionError, err:
multi.append_properties_error(err)
if not one_has_value:
#raise last err
raise err
return multi
def setitem(self, values, opt, value, path):
if self.is_master(opt):
@ -241,15 +229,6 @@ class MasterSlaves(object):
slave_path = base_path + slave.impl_getname()
slavelen = values._p_.get_max_length(slave_path)
self.validate_slave_length(masterlen, slavelen, slave.impl_getname(), opt)
#slave_value = values._get_validated_value(slave,
# slave_path,
# False,
# False,
# None, False,
# None,
# masterlen=masterlen) # not undefined
#slavelen = len(slave_value)
#self.validate_slave_length(masterlen, slavelen, slave.impl_getname(), opt)
else:
self.validate_slave_length(self.get_length(values, opt,
slave_path=path), len(value),

View File

@ -23,12 +23,12 @@ import re
import sys
from IPy import IP
from types import FunctionType
from tiramisu.setting import log, undefined
from ..setting import log, undefined
from tiramisu.error import ConfigError, ContextError
from tiramisu.i18n import _
from ..error import ConfigError, ContextError
from ..i18n import _
from .baseoption import Option, validate_callback
from tiramisu.autolib import carry_out_calculation
from ..autolib import carry_out_calculation
class ChoiceOption(Option):

View File

@ -22,13 +22,13 @@ from copy import copy
import re
from tiramisu.i18n import _
from tiramisu.setting import groups, undefined # , log
from ..i18n import _
from ..setting import groups, undefined # , log
from .baseoption import BaseOption, SymLinkOption, allowed_character
from . import MasterSlaves
from tiramisu.error import ConfigError, ConflictError
from tiramisu.storage import get_storages_option
from tiramisu.autolib import carry_out_calculation
from ..error import ConfigError, ConflictError
from ..storage import get_storages_option
from ..autolib import carry_out_calculation
StorageOptionDescription = get_storages_option('optiondescription')
@ -135,6 +135,19 @@ class OptionDescription(BaseOption, StorageOptionDescription):
option._set_readonly()
if isinstance(option, OptionDescription):
option.impl_validate_options(cache_option)
if option.impl_getrequires() != []:
for requires in option.impl_getrequires():
for require in requires:
if require[0].impl_is_multi():
if option.impl_is_master_slaves('slave') and require[0].impl_is_master_slaves():
if option.impl_get_master_slaves() != require[0].impl_get_master_slaves():
raise ValueError(_('malformed requirements option {0} '
'must be in same master/slaves for {1}').format(
require[0].impl_getname(), option.impl_getname()))
else:
raise ValueError(_('malformed requirements option {0} '
'must not be a multi for {1}').format(
require[0].impl_getname(), option.impl_getname()))
if init:
if len(cache_option) != len(set(cache_option)):
for idx in xrange(1, len(cache_option) + 1):

View File

@ -19,9 +19,9 @@ from time import time
from copy import copy
from logging import getLogger
import weakref
from tiramisu.error import (RequirementError, PropertiesOptionError,
ConstError, ConfigError)
from tiramisu.i18n import _
from .error import (RequirementError, PropertiesOptionError,
ConstError, ConfigError)
from .i18n import _
"Default encoding for display a Config if raise UnicodeEncodeError"
@ -367,7 +367,7 @@ class Settings(object):
def _getproperties(self, opt=None, path=None,
setting_properties=undefined, read_write=True,
apply_requires=True):
apply_requires=True, index=None):
"""
"""
if opt is None:
@ -384,17 +384,17 @@ class Settings(object):
ntime = int(time())
else:
ntime = None
if 'cache' in setting_properties and self._p_.hascache(path):
is_cached, props = self._p_.getcache(path, ntime)
if 'cache' in setting_properties and self._p_.hascache(path, index):
is_cached, props = self._p_.getcache(path, ntime, index)
if not is_cached:
props = self._p_.getproperties(path, opt.impl_getproperties())
if apply_requires:
props = copy(props)
props |= self.apply_requires(opt, path, setting_properties)
props |= self.apply_requires(opt, path, setting_properties, index)
if 'cache' in setting_properties:
if 'expire' in setting_properties:
ntime = ntime + expires_time
self._p_.setcache(path, props, ntime)
self._p_.setcache(path, props, ntime, index)
if read_write:
props = copy(props)
return props
@ -458,7 +458,8 @@ class Settings(object):
properties = copy(self_properties)
else:
properties = self._getproperties(opt_or_descr, path,
setting_properties=setting_properties)
setting_properties=setting_properties,
index=index)
# remove opt permissive
# permissive affect option's permission with or without permissive
# global property
@ -571,7 +572,7 @@ class Settings(object):
else:
self._p_.reset_all_cache()
def apply_requires(self, opt, path, setting_properties):
def apply_requires(self, opt, path, setting_properties, index):
"""carries out the jit (just in time) requirements between options
a requirement is a tuple of this form that comes from the option's
@ -633,7 +634,8 @@ class Settings(object):
"'{1}'").format(path, reqpath))
try:
value = context.getattr(reqpath, force_permissive=True,
_setting_properties=setting_properties)
_setting_properties=setting_properties,
index=index)
except PropertiesOptionError as err:
if not transitive:
continue

View File

@ -29,8 +29,11 @@ configurator ``set_storage()``.
from time import time
from random import randint
import os
from tiramisu.error import ConfigError
from tiramisu.i18n import _
from ..error import ConfigError
from ..i18n import _
MODULE_PATH = os.path.split(os.path.split(os.path.split(__file__)[0])[0])[1]
class StorageType(object):
@ -53,7 +56,7 @@ class StorageType(object):
if self.storage_type is None:
self.storage_type = self.default_storage
if self.mod is None:
modulepath = 'tiramisu.storage.{0}'.format(self.storage_type)
modulepath = '{0}.storage.{1}'.format(MODULE_PATH, self.storage_type)
try:
mod = __import__(modulepath)
except ImportError:

View File

@ -17,9 +17,9 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# ____________________________________________________________
from tiramisu.i18n import _
from tiramisu.setting import undefined
from tiramisu.error import ConfigError
from ...i18n import _
from ...setting import undefined
from ...error import ConfigError
#____________________________________________________________

View File

@ -14,8 +14,8 @@
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# ____________________________________________________________
from tiramisu.i18n import _
from tiramisu.error import ConfigError
from ...i18n import _
from ...error import ConfigError
from ..util import SerializeObject

View File

@ -16,7 +16,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# ____________________________________________________________
from ..util import Cache
from tiramisu.setting import undefined
from ...setting import undefined
class Values(Cache):

View File

@ -15,7 +15,7 @@
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# ____________________________________________________________
from tiramisu.setting import owners
from ..setting import owners
class SerializeObject(object):
@ -97,27 +97,30 @@ class Cache(object):
value = tuple(_value)
setattr(self, key, value)
def setcache(self, path, val, time):
self._cache[path] = (val, time)
def setcache(self, path, val, time, index):
self._cache.setdefault(path, {})[index] = (val, time)
def getcache(self, path, exp):
value, created = self._cache[path]
def getcache(self, path, exp, index):
value, created = self._cache[path][index]
if created is None or exp <= created:
return True, value
return False, None
def hascache(self, path):
def hascache(self, path, index):
""" path is in the cache
:param path: the path's option
"""
return path in self._cache
return path in self._cache and index in self._cache[path]
def reset_expired_cache(self, exp):
for key in tuple(self._cache.keys()):
val, created = self._cache[key]
if created is not None and exp > created:
del(self._cache[key])
for key in self._cache.keys():
for index in self._cache[key].keys():
val, created = self._cache[key][index]
if created is not None and exp > created:
del(self._cache[key][index])
if self._cache[key] == {}:
del(self._cache[key])
def reset_all_cache(self):
"empty the cache"
@ -125,6 +128,6 @@ class Cache(object):
def get_cached(self, context):
"""return all values in a dictionary
example: {'path1': ('value1', 'time1'), 'path2': ('value2', 'time2')}
example: {'path1': {'index1': ('value1', 'time1')}, 'path2': {'index2': ('value2', 'time2', )}}
"""
return self._cache

View File

@ -18,11 +18,11 @@
from time import time
import sys
import weakref
from tiramisu.error import ConfigError, SlaveError, PropertiesOptionError
from tiramisu.setting import owners, expires_time, undefined
from tiramisu.autolib import carry_out_calculation
from tiramisu.i18n import _
from tiramisu.option import SymLinkOption, DynSymLinkOption, Option
from .error import ConfigError, SlaveError, PropertiesOptionError
from .setting import owners, expires_time, undefined
from .autolib import carry_out_calculation
from .i18n import _
from .option import SymLinkOption, DynSymLinkOption, Option
class Values(object):
@ -65,7 +65,7 @@ class Values(object):
callback=callback,
callback_params=callback_params,
index=index)
if isinstance(value, list) and index is not undefined:
if isinstance(value, list) and index is not None:
#if return a list and index is set, return value only if
#it's a submulti without submulti_index and without list of list
if opt.impl_is_submulti() and submulti_index is undefined and \
@ -78,9 +78,9 @@ class Values(object):
if meta is not None:
try:
value = meta.cfgimpl_get_values(
)._get_cached_item(opt, path)
)._get_cached_value(opt, path, index=index, from_masterslave=True)
if isinstance(value, Multi):
if index is not undefined:
if index is not None:
value = value[index]
else:
value = list(value)
@ -89,7 +89,7 @@ class Values(object):
pass
# now try to get default value
value = opt.impl_getdefault()
if opt.impl_is_multi() and index is not undefined:
if opt.impl_is_multi() and index is not None:
if value == []:
value = opt.impl_getdefault_multi()
else:
@ -115,7 +115,7 @@ class Values(object):
return self._p_.getvalue(path, index)
else:
value = self._p_.getvalue(path)
if index is not undefined:
if index is not None:
try:
return value[index]
except IndexError:
@ -204,13 +204,15 @@ class Values(object):
def getitem(self, opt, validate=True, force_permissive=False):
"""
"""
return self._get_cached_item(opt, validate=validate,
force_permissive=force_permissive)
return self._get_cached_value(opt, validate=validate,
force_permissive=force_permissive)
def _get_cached_item(self, opt, path=None, validate=True,
force_permissive=False, force_properties=None,
validate_properties=True,
setting_properties=undefined, self_properties=undefined):
def _get_cached_value(self, opt, path=None, validate=True,
force_permissive=False, force_properties=None,
validate_properties=True,
setting_properties=undefined, self_properties=undefined,
index=None, from_masterslave=False, with_meta=True,
masterlen=undefined):
untrusted_cached_properties = force_properties is None
context = self._getcontext()
if path is None:
@ -221,13 +223,14 @@ class Values(object):
)._getproperties(read_write=False)
if self_properties is undefined:
self_properties = context.cfgimpl_get_settings()._getproperties(
opt, path, read_write=False, setting_properties=setting_properties)
if 'cache' in setting_properties and self._p_.hascache(path):
opt, path, read_write=False,
setting_properties=setting_properties, index=index)
if 'cache' in setting_properties and self._p_.hascache(path, index):
if 'expire' in setting_properties:
ntime = int(time())
is_cached, value = self._p_.getcache(path, ntime)
is_cached, value = self._p_.getcache(path, ntime, index)
if is_cached:
if opt.impl_is_multi() and not isinstance(value, Multi):
if opt.impl_is_multi() and not isinstance(value, Multi) and index is None:
value = Multi(value, self.context, opt, path)
if not untrusted_cached_properties:
# revalidate properties (because not default properties)
@ -236,42 +239,41 @@ class Values(object):
force_permissive=force_permissive,
force_properties=force_properties,
setting_properties=setting_properties,
self_properties=self_properties)
self_properties=self_properties,
index=index)
return value
val = self._getitem(opt, path, validate, force_permissive,
force_properties, validate_properties,
setting_properties, self_properties=self_properties)
if 'cache' in setting_properties and validate and validate_properties \
if not from_masterslave and opt.impl_is_master_slaves():
val = opt.impl_get_master_slaves().getitem(self, opt, path,
validate,
force_permissive,
force_properties,
validate_properties,
setting_properties=setting_properties,
index=index,
self_properties=self_properties)
else:
val = self._get_validated_value(opt, path, validate,
force_permissive,
force_properties,
validate_properties,
setting_properties=setting_properties,
self_properties=self_properties,
with_meta=with_meta,
masterlen=masterlen,
index=index)
# cache doesn't work with SubMulti yet
if not isinstance(val, SubMulti) and 'cache' in setting_properties and validate and validate_properties \
and force_permissive is False and force_properties is None:
if 'expire' in setting_properties:
if ntime is None:
ntime = int(time())
ntime = ntime + expires_time
self._p_.setcache(path, val, ntime)
self._p_.setcache(path, val, ntime, index)
return val
def _getitem(self, opt, path, validate, force_permissive, force_properties,
validate_properties, setting_properties=undefined,
self_properties=undefined):
if opt.impl_is_master_slaves():
return opt.impl_get_master_slaves().getitem(self, opt, path,
validate,
force_permissive,
force_properties,
validate_properties,
setting_properties=setting_properties,
self_properties=self_properties)
else:
return self._get_validated_value(opt, path, validate,
force_permissive,
force_properties,
validate_properties,
setting_properties=setting_properties,
self_properties=self_properties)
def _get_validated_value(self, opt, path, validate, force_permissive,
force_properties, validate_properties,
index=undefined, submulti_index=undefined,
index=None, submulti_index=undefined,
with_meta=True, setting_properties=undefined,
self_properties=undefined, masterlen=undefined):
"""same has getitem but don't touch the cache
@ -282,7 +284,7 @@ class Values(object):
if setting_properties is undefined:
setting_properties = setting._getproperties(read_write=False)
if self_properties is undefined:
self_properties = setting._getproperties(opt, path, read_write=False)
self_properties = setting._getproperties(opt, path, read_write=False, index=index)
is_default = self._is_default_owner(opt, path,
validate_properties=False,
validate_meta=False,
@ -458,8 +460,8 @@ class Values(object):
if 'frozen' in self_properties and 'force_default_on_freeze' in self_properties:
return owners.default
if validate_properties:
self._getitem(opt, path, True, force_permissive, None, True,
self_properties=self_properties)
self._get_cached_value(opt, path, True, force_permissive, None, True,
self_properties=self_properties)
owner = self._p_.getowner(path, owners.default, only_default=only_default, index=index)
if validate_meta is undefined:
if opt.impl_is_master_slaves('slave'):
@ -601,12 +603,12 @@ class Values(object):
setting_properties=setting_properties)
if 'mandatory' in self_properties:
try:
self._get_cached_item(true_opt, path=true_path,
force_properties=frozenset(('mandatory',)),
force_permissive=force_permissive,
setting_properties=setting_properties,
self_properties=self_properties,
validate=validate)
self._get_cached_value(true_opt, path=true_path,
force_properties=frozenset(('mandatory',)),
force_permissive=force_permissive,
setting_properties=setting_properties,
self_properties=self_properties,
validate=validate)
except PropertiesOptionError as err:
if err.proptype == ['mandatory']:
yield path
@ -710,7 +712,7 @@ class Multi(list):
setting_properties = setting._getproperties(read_write=False)
if 'validator' in setting_properties and validate:
fake_context = context._gen_fake_values()
fake_multi = fake_context.cfgimpl_get_values()._get_cached_item(
fake_multi = fake_context.cfgimpl_get_values()._get_cached_value(
self.opt, path=self.path, validate=False)
fake_multi._setitem(index, value, validate=False)
self._validate(value, fake_context, index, True)
@ -721,8 +723,11 @@ class Multi(list):
#def __repr__(self, *args, **kwargs):
# return super(Multi, self).__repr__(*args, **kwargs)
#def __getitem__(self, y):
# return super(Multi, self).__getitem__(y)
def __getitem__(self, index):
value = super(Multi, self).__getitem__(index)
if isinstance(value, PropertiesOptionError):
raise value
return value
def _get_validated_value(self, index):
values = self._getcontext().cfgimpl_get_values()
@ -740,15 +745,16 @@ class Multi(list):
index = self.__len__()
if value is undefined:
value = self._get_validated_value(index)
context = self._getcontext()
setting = context.cfgimpl_get_settings()
setting_properties = setting._getproperties(read_write=False)
if 'validator' in setting_properties and validate and value not in [None, undefined]:
fake_context = context._gen_fake_values()
fake_multi = fake_context.cfgimpl_get_values()._get_cached_item(
self.opt, path=self.path, validate=False)
fake_multi.append(value, validate=False, force=True)
self._validate(value, fake_context, index, True)
if validate and value not in [None, undefined]:
context = self._getcontext()
setting = context.cfgimpl_get_settings()
setting_properties = setting._getproperties(read_write=False)
if 'validator' in setting_properties:
fake_context = context._gen_fake_values()
fake_multi = fake_context.cfgimpl_get_values()._get_cached_value(
self.opt, path=self.path, validate=False)
fake_multi.append(value, validate=False, force=True)
self._validate(value, fake_context, index, True)
if not '_index' in self.__slots__ and self.opt.impl_is_submulti():
if not isinstance(value, SubMulti):
value = SubMulti(value, self.context, self.opt, self.path, index)
@ -757,6 +763,9 @@ class Multi(list):
if setitem:
self._store(force=force)
def append_properties_error(self, err):
super(Multi, self).append(err)
def sort(self, cmp=None, key=None, reverse=False):
if self.opt.impl_is_master_slaves():
raise SlaveError(_("cannot sort multi option {0} if master or slave"
@ -786,7 +795,7 @@ class Multi(list):
setting_properties = setting._getproperties(read_write=False)
if 'validator' in setting_properties and validate and value is not None:
fake_context = context._gen_fake_values()
fake_multi = fake_context.cfgimpl_get_values()._get_cached_item(
fake_multi = fake_context.cfgimpl_get_values()._get_cached_value(
self.opt, path=self.path, validate=False)
fake_multi.insert(index, value, validate=False)
self._validate(value, fake_context, index, True)
@ -806,7 +815,7 @@ class Multi(list):
setting_properties = setting._getproperties(read_write=False)
if 'validator' in setting_properties and validate:
fake_context = context._gen_fake_values()
fake_multi = fake_context.cfgimpl_get_values()._get_cached_item(
fake_multi = fake_context.cfgimpl_get_values()._get_cached_value(
self.opt, path=self.path, validate=False)
fake_multi.extend(iterable, validate=False)
self._validate(iterable, fake_context, index)