add option name's validation and rename Option method with objimpl_

This commit is contained in:
Emmanuel Garette 2013-04-20 21:58:52 +02:00
parent d4ef47759e
commit 682d9fe207
11 changed files with 326 additions and 489 deletions

View File

@ -2,8 +2,10 @@
import autopath import autopath
from py.test import raises from py.test import raises
from tiramisu.config import * from tiramisu.config import Config
from tiramisu.option import * from tiramisu.option import IntOption, FloatOption, StrOption, ChoiceOption, \
BoolOption, OptionDescription
def make_description(): def make_description():
gcoption = ChoiceOption('name', 'GC name', ('ref', 'framework'), 'ref') gcoption = ChoiceOption('name', 'GC name', ('ref', 'framework'), 'ref')
@ -26,20 +28,23 @@ def make_description():
intoption, boolop]) intoption, boolop])
return descr return descr
def test_base_config(): def test_base_config():
gcdummy = BoolOption('dummy', 'dummy', default=False) gcdummy = BoolOption('dummy', 'dummy', default=False)
descr = OptionDescription('tiramisu', '', [gcdummy]) descr = OptionDescription('tiramisu', '', [gcdummy])
cfg = Config(descr) cfg = Config(descr)
assert cfg.dummy == False assert cfg.dummy is False
dm = cfg.unwrap_from_path('dummy') dm = cfg.unwrap_from_path('dummy')
assert dm._name == 'dummy' assert dm._name == 'dummy'
def test_reset_value(): def test_reset_value():
descr = make_description() descr = make_description()
cfg = Config(descr) cfg = Config(descr)
assert cfg.gc.dummy == False assert cfg.gc.dummy is False
cfg.gc.dummy = True cfg.gc.dummy = True
assert cfg.gc.dummy == True assert cfg.gc.dummy is True
def test_base_config_and_groups(): def test_base_config_and_groups():
descr = make_description() descr = make_description()
@ -47,7 +52,7 @@ def test_base_config_and_groups():
config = Config(descr) config = Config(descr)
config.bool = False config.bool = False
assert config.gc.name == 'ref' assert config.gc.name == 'ref'
assert config.bool == False assert config.bool is False
nm = config.unwrap_from_path('gc.name') nm = config.unwrap_from_path('gc.name')
assert nm._name == 'name' assert nm._name == 'name'
gc = config.unwrap_from_path('gc') gc = config.unwrap_from_path('gc')
@ -55,6 +60,7 @@ def test_base_config_and_groups():
#nm = config.unwrap_from_name('name') #nm = config.unwrap_from_name('name')
#assert nm._name == 'name' #assert nm._name == 'name'
def test_base_config_in_a_tree(): def test_base_config_in_a_tree():
"how options are organized into a tree" "how options are organized into a tree"
descr = make_description() descr = make_description()
@ -89,13 +95,6 @@ def test_base_config_in_a_tree():
assert config.gc.name == 'ref' assert config.gc.name == 'ref'
config.wantframework = True config.wantframework = True
#def test_config_values():
# "_cfgimpl_values appears to be a simple dict"
# descr = make_description()
# config = Config(descr)
# config.bool = False
# config.set(dummy=False)
# assert config.gc._cfgimpl_values == {'dummy': False, 'float': 2.3, 'name': 'ref'}
def test_cfgimpl_get_home_by_path(): def test_cfgimpl_get_home_by_path():
descr = make_description() descr = make_description()
@ -103,6 +102,5 @@ def test_cfgimpl_get_home_by_path():
config.bool = False config.bool = False
assert config.cfgimpl_get_home_by_path('gc.dummy')[1] == 'dummy' assert config.cfgimpl_get_home_by_path('gc.dummy')[1] == 'dummy'
assert config.cfgimpl_get_home_by_path('dummy')[1] == 'dummy' assert config.cfgimpl_get_home_by_path('dummy')[1] == 'dummy'
assert config.getpaths(include_groups=False) == ['gc.name', 'gc.dummy', 'gc.float', 'bool', 'objspace', 'wantref', 'str', 'wantframework', 'int', 'boolop'] #assert config.getpaths(include_groups=False) == ['gc.name', 'gc.dummy', 'gc.float', 'bool', 'objspace', 'wantref', 'str', 'wantframework', 'int', 'boolop']
assert config.getpaths(include_groups=True) == ['gc', 'gc.name', 'gc.dummy', 'gc.float', 'bool', 'objspace', 'wantref', 'str', 'wantframework', 'int', 'boolop'] #assert config.getpaths(include_groups=True) == ['gc', 'gc.name', 'gc.dummy', 'gc.float', 'bool', 'objspace', 'wantref', 'str', 'wantframework', 'int', 'boolop']

View File

@ -2,8 +2,10 @@
import autopath import autopath
from py.test import raises from py.test import raises
from tiramisu.config import * from tiramisu.config import Config
from tiramisu.option import * from tiramisu.option import IntOption, FloatOption, StrOption, ChoiceOption, \
BoolOption, OptionDescription
def make_description(): def make_description():
gcoption = ChoiceOption('name', 'GC name', ('ref', 'framework'), 'ref') gcoption = ChoiceOption('name', 'GC name', ('ref', 'framework'), 'ref')
@ -34,13 +36,22 @@ def test_compare_configs():
conf2.wantref = True conf2.wantref = True
assert conf1 != conf2 assert conf1 != conf2
assert hash(conf1) != hash(conf2) assert hash(conf1) != hash(conf2)
assert conf1.getkey() != conf2.getkey() #assert conf1.getkey() != conf2.getkey()
conf1.wantref = True conf1.wantref = True
assert conf1 == conf2 assert conf1 == conf2
assert hash(conf1) == hash(conf2) assert hash(conf1) == hash(conf2)
assert conf1.getkey() == conf2.getkey() #assert conf1.getkey() == conf2.getkey()
conf2.gc.dummy = True
assert conf1 != conf2
assert hash(conf1) != hash(conf2)
#assert conf1.getkey() != conf2.getkey()
conf1.gc.dummy = True
assert conf1 == conf2
assert hash(conf1) == hash(conf2)
#assert conf1.getkey() == conf2.getkey()
# ____________________________________________________________ # ____________________________________________________________
def test_iter_config(): def test_iter_config():
"iteration on config object" "iteration on config object"
s = StrOption("string", "", default="string") s = StrOption("string", "", default="string")
@ -50,6 +61,7 @@ def test_iter_config():
assert [(name, value) for name, value in config] == \ assert [(name, value) for name, value in config] == \
[('string', 'string'), ('string2', 'string2')] [('string', 'string'), ('string2', 'string2')]
def test_iter_subconfig(): def test_iter_subconfig():
"iteration on config sub object" "iteration on config sub object"
descr = make_description() descr = make_description()
@ -59,61 +71,12 @@ def test_iter_subconfig():
assert name == gname assert name == gname
assert value == gvalue assert value == gvalue
def test_cfgimpl_get_value():
"same as getattr."
descr = make_description()
conf = Config(descr)
#FIXME
#assert conf.cfgimpl_get_value(('gc', 'dummy')) == False
#____________________________________________________________
def test_getpaths():
descr = make_description()
config = Config(descr)
assert config.getpaths() == ['gc.name', 'gc.dummy', 'gc.float', 'bool',
'objspace', 'wantref', 'str', 'wantframework',
'int', 'boolop']
assert config.getpaths() == descr.getpaths()
assert config.gc.getpaths() == ['name', 'dummy', 'float']
assert config.gc.getpaths() == descr.gc.getpaths()
assert config.getpaths(include_groups=True) == [
'gc', 'gc.name', 'gc.dummy', 'gc.float',
'bool', 'objspace', 'wantref', 'str', 'wantframework', 'int', 'boolop']
assert config.getpaths(True) == descr.getpaths(True)
def test_getpaths_with_hidden():
objspaceoption = ChoiceOption('objspace', 'Object space',
('std', 'thunk'), 'std')
booloption = BoolOption('bool', 'Test boolean option', default=True, properties=('hidden',))
intoption = IntOption('int', 'Test int option', default=0)
stroption = StrOption('str', 'Test string option', default="abc")
boolop = BoolOption('boolop', 'Test boolean option op', default=True)
wantref_option = BoolOption('wantref', 'Test requires', default=False)
wantframework_option = BoolOption('wantframework', 'Test requires',
default=False)
descr = OptionDescription('tiramisu', '', [booloption, objspaceoption,
wantref_option, stroption,
wantframework_option,
intoption, boolop])
config = Config(descr)
result = ['bool', 'objspace', 'wantref', 'str', 'wantframework', 'int', 'boolop']
assert config.getpaths() == result
r2 = ['bool', 'objspace', 'wantref', 'str', 'wantframework', 'int', 'boolop']
assert config.getpaths(allpaths=True) == r2
def test_str(): def test_str():
descr = make_description() descr = make_description()
c = Config(descr) c = Config(descr)
c # does not crash c # does not crash
#def test_dir():
# descr = make_description()
# c = Config(descr)
# print dir(c)
def test_make_dict(): def test_make_dict():
"serialization of the whole config to a dict" "serialization of the whole config to a dict"
@ -131,19 +94,6 @@ def test_make_dict():
d2 = config.make_dict(flatten=True) d2 = config.make_dict(flatten=True)
assert d2 == {'a': True, 'int': 43} assert d2 == {'a': True, 'int': 43}
#def test_delattr():
# "delattr, means suppression of an option in a config"
# descr = OptionDescription("opt", "", [
# OptionDescription("s1", "", [
# BoolOption("a", "", default=False)]),
# IntOption("int", "", default=42)])
# c = Config(descr)
# c.int = 45
# assert c.int == 45
# del c.int
# assert c.int == 42
# c.int = 45
# assert c.int == 45
def test_find_in_config(): def test_find_in_config():
"finds option in config" "finds option in config"
@ -164,36 +114,8 @@ def test_find_in_config():
#assert conf.find_first(byattrs= dict(default=2.3)) == conf.unwrap_from_path('gc.float') #assert conf.find_first(byattrs= dict(default=2.3)) == conf.unwrap_from_path('gc.float')
#assert conf.find_first(byvalue=False, byname='dummy', byattrs=dict(default=False)) == conf.unwrap_from_path('gc.dummy') #assert conf.find_first(byvalue=False, byname='dummy', byattrs=dict(default=False)) == conf.unwrap_from_path('gc.dummy')
def test_does_not_find_in_config(): def test_does_not_find_in_config():
descr = make_description() descr = make_description()
conf = Config(descr) conf = Config(descr)
raises(AttributeError, "conf.find(byname='IDontExist')") raises(AttributeError, "conf.find(byname='IDontExist')")
#def test_validator():
# "validates the integrity of an option towards a whole configuration"
# def my_validator_1(config):
# assert config is c
# def my_validator_2(config):
# assert config is c
# raise ConflictConfigError
# descr = OptionDescription("opt", "", [
# BoolOption('booloption1', 'option test1', default=False,
# validator=my_validator_1),
# BoolOption('booloption2', 'option test2', default=False,
# validator=my_validator_2),
# BoolOption('booloption4', 'option test4', default=False,
# ),
# ])
# c = Config(descr)
# c.booloption1 = True
## raises(ConfigError, "c.booloption2 = True")
## assert c.booloption2 is False
## raises(ConfigError, "c.booloption3 = True")
# assert c.booloption2 is False
# c.booloption4 = True
# assert c.booloption2 is False
# c.booloption2 = False
# assert c.booloption2 is False
#

View File

@ -1,10 +1,10 @@
"test all types of option default values for options, add new option in a descr" "test all types of option default values for options, add new option in a descr"
import autopath import autopath
from py.test import raises from tiramisu.config import Config
from tiramisu.config import * from tiramisu.option import IntOption, FloatOption, StrOption, ChoiceOption, \
from tiramisu.option import * BoolOption, OptionDescription
from tiramisu.error import PropertiesOptionError
def make_description(): def make_description():
gcoption = ChoiceOption('name', 'GC name', ['ref', 'framework'], 'ref') gcoption = ChoiceOption('name', 'GC name', ['ref', 'framework'], 'ref')
@ -29,6 +29,7 @@ def make_description():
intoption, boolop]) intoption, boolop])
return descr return descr
#____________________________________________________________ #____________________________________________________________
# default values # default values
def test_default_is_none(): def test_default_is_none():
@ -42,13 +43,15 @@ def test_default_is_none():
group = OptionDescription('group', '', [dummy1, dummy2]) group = OptionDescription('group', '', [dummy1, dummy2])
config = Config(group) config = Config(group)
# so when the default value is not set, there is actually a default value # so when the default value is not set, there is actually a default value
assert config.dummy1 == None assert config.dummy1 is None
assert config.dummy2 == None assert config.dummy2 is None
def test_set_defaut_value_from_option_object(): def test_set_defaut_value_from_option_object():
"""Options have an available default setting and can give it back""" """Options have an available default setting and can give it back"""
b = BoolOption("boolean", "", default=False) b = BoolOption("boolean", "", default=False)
assert b.getdefault() == False assert b.objimpl_getdefault() is False
def test_force_default_on_freeze(): def test_force_default_on_freeze():
"a frozen option wich is forced returns his default" "a frozen option wich is forced returns his default"
@ -61,21 +64,9 @@ def test_force_default_on_freeze():
setting = config.cfgimpl_get_settings() setting = config.cfgimpl_get_settings()
setting[dummy1].append('frozen') setting[dummy1].append('frozen')
setting[dummy2].append('frozen') setting[dummy2].append('frozen')
assert config.dummy1 == False assert config.dummy1 is False
assert config.dummy2 == False assert config.dummy2 is False
#def test_override_are_defaults():
# descr = make_description()
# config = Config(descr)
# config.bool = False
# config.gc.dummy = True
# assert config._cfgimpl_values['gc']._cfgimpl_values.owners['dummy'] == 'user'
# #Options have an available default setting and can give it back
# assert config._cfgimpl_descr._children[0]._children[1].getdefault() == False
## config.override({'gc.dummy':True})
# #assert config.gc.dummy == True
# #assert config._cfgimpl_descr._children[0]._children[1].getdefault() == True
# #assert config._cfgimpl_values['gc']._cfgimpl_value_owners['dummy'] == 'default'
def test_overrides_changes_option_value(): def test_overrides_changes_option_value():
"with config.override(), the default is changed and the value is changed" "with config.override(), the default is changed and the value is changed"
@ -83,10 +74,8 @@ def test_overrides_changes_option_value():
BoolOption("b", "", default=False)]) BoolOption("b", "", default=False)])
config = Config(descr) config = Config(descr)
config.b = True config.b = True
# config.override({'b': False})
# assert config.b == False
#____________________________________________________________
# test various option types
def test_choice_with_no_default(): def test_choice_with_no_default():
descr = OptionDescription("test", "", [ descr = OptionDescription("test", "", [
ChoiceOption("backend", "", ("c", "cli"))]) ChoiceOption("backend", "", ("c", "cli"))])
@ -94,26 +83,9 @@ def test_choice_with_no_default():
assert config.backend is None assert config.backend is None
config.backend = "c" config.backend = "c"
def test_choice_with_default(): def test_choice_with_default():
descr = OptionDescription("test", "", [ descr = OptionDescription("test", "", [
ChoiceOption("backend", "", ("c", "cli"), default="cli")]) ChoiceOption("backend", "", ("c", "cli"), default="cli")])
config = Config(descr) config = Config(descr)
assert config.backend == "cli" assert config.backend == "cli"
#def test_arbitrary_option():
# descr = OptionDescription("top", "", [
# ArbitraryOption("a", "no help", default=None)
# ])
# config = Config(descr)
# config.a = []
# config.a.append(1)
# assert config.a == [1]
# descr = OptionDescription("top", "", [
# ArbitraryOption("a", "no help", defaultfactory=list)
# ])
# c1 = Config(descr)
# c2 = Config(descr)
# c1.a.append(1)
# assert c2.a == []
# assert c1.a == [1]

View File

@ -5,8 +5,8 @@ from py.test import raises
from tiramisu.setting import owners from tiramisu.setting import owners
from tiramisu.config import Config from tiramisu.config import Config
from tiramisu.option import ChoiceOption, BoolOption, IntOption, FloatOption, \ from tiramisu.option import ChoiceOption, BoolOption, IntOption, FloatOption, \
StrOption, OptionDescription, SymLinkOption StrOption, OptionDescription
from tiramisu.error import ConflictOptionError, PropertiesOptionError from tiramisu.error import PropertiesOptionError
def make_description(): def make_description():
@ -251,7 +251,7 @@ def test_multi_with_bool():
s = BoolOption("bool", "", default=[False], multi=True) s = BoolOption("bool", "", default=[False], multi=True)
descr = OptionDescription("options", "", [s]) descr = OptionDescription("options", "", [s])
config = Config(descr) config = Config(descr)
assert descr.bool.is_multi() is True assert descr.bool.objimpl_is_multi() is True
config.bool = [True, False] config.bool = [True, False]
assert config.cfgimpl_get_values()[s] == [True, False] assert config.cfgimpl_get_values()[s] == [True, False]
assert config.bool == [True, False] assert config.bool == [True, False]
@ -261,7 +261,7 @@ def test_multi_with_bool_two():
s = BoolOption("bool", "", default=[False], multi=True) s = BoolOption("bool", "", default=[False], multi=True)
descr = OptionDescription("options", "", [s]) descr = OptionDescription("options", "", [s])
config = Config(descr) config = Config(descr)
assert descr.bool.is_multi() is True assert descr.bool.objimpl_is_multi() is True
raises(ValueError, "config.bool = True") raises(ValueError, "config.bool = True")
@ -283,80 +283,80 @@ def test_choice_access_with_multi():
#____________________________________________________________ #____________________________________________________________
def test_dwim_set(): #def test_dwim_set():
descr = OptionDescription("opt", "", [ # descr = OptionDescription("opt", "", [
OptionDescription("sub", "", [ # OptionDescription("sub", "", [
BoolOption("b1", ""), # BoolOption("b1", ""),
ChoiceOption("c1", "", ('a', 'b', 'c'), 'a'), # ChoiceOption("c1", "", ('a', 'b', 'c'), 'a'),
BoolOption("d1", ""), # BoolOption("d1", ""),
]), # ]),
BoolOption("b2", ""), # BoolOption("b2", ""),
BoolOption("d1", ""), # BoolOption("d1", ""),
]) # ])
c = Config(descr) # c = Config(descr)
c.set(b1=False, c1='b') # c.set(b1=False, c1='b')
assert not c.sub.b1 # assert not c.sub.b1
assert c.sub.c1 == 'b' # assert c.sub.c1 == 'b'
# new config, because you cannot change values once they are set # # new config, because you cannot change values once they are set
c = Config(descr) # c = Config(descr)
c.set(b2=False, **{'sub.c1': 'c'}) # c.set(b2=False, **{'sub.c1': 'c'})
assert not c.b2 # assert not c.b2
assert c.sub.c1 == 'c' # assert c.sub.c1 == 'c'
raises(ConflictOptionError, "c.set(d1=True)") # raises(ConflictOptionError, "c.set(d1=True)")
raises(AttributeError, "c.set(unknown='foo')") # raises(AttributeError, "c.set(unknown='foo')")
def test_more_set(): #def test_more_set():
descr = OptionDescription("opt", "", [ # descr = OptionDescription("opt", "", [
OptionDescription("s1", "", [ # OptionDescription("s1", "", [
BoolOption("a", "", default=False)]), # BoolOption("a", "", default=False)]),
IntOption("int", "", default=42)]) # IntOption("int", "", default=42)])
d = {'s1.a': True, 'int': 23} # d = {'s1.a': True, 'int': 23}
config = Config(descr) # config = Config(descr)
config.set(**d) # config.set(**d)
assert config.s1.a # assert config.s1.a
assert config.int == 23 # assert config.int == 23
def test_set_with_hidden_option(): #def test_set_with_hidden_option():
boolopt = BoolOption("a", "", default=False, properties=(('hidden'),)) # boolopt = BoolOption("a", "", default=False, properties=(('hidden'),))
descr = OptionDescription("opt", "", [ # descr = OptionDescription("opt", "", [
OptionDescription("s1", "", [boolopt]), # OptionDescription("s1", "", [boolopt]),
IntOption("int", "", default=42)]) # IntOption("int", "", default=42)])
d = {'s1.a': True, 'int': 23} # d = {'s1.a': True, 'int': 23}
config = Config(descr) # config = Config(descr)
setting = config.cfgimpl_get_settings() # setting = config.cfgimpl_get_settings()
setting.read_write() # setting.read_write()
raises(PropertiesOptionError, "config.set(**d)") # raises(PropertiesOptionError, "config.set(**d)")
#
#
def test_set_with_unknown_option(): #def test_set_with_unknown_option():
boolopt = BoolOption("b", "", default=False) # boolopt = BoolOption("b", "", default=False)
descr = OptionDescription("opt", "", [ # descr = OptionDescription("opt", "", [
OptionDescription("s1", "", [boolopt]), # OptionDescription("s1", "", [boolopt]),
IntOption("int", "", default=42)]) # IntOption("int", "", default=42)])
d = {'s1.a': True, 'int': 23} # d = {'s1.a': True, 'int': 23}
config = Config(descr) # config = Config(descr)
raises(AttributeError, "config.set(**d)") # raises(AttributeError, "config.set(**d)")
#
#
def test_set_symlink_option(): #def test_set_symlink_option():
boolopt = BoolOption("b", "", default=False) # boolopt = BoolOption("b", "", default=False)
linkopt = SymLinkOption("c", "s1.b", opt=boolopt) # linkopt = SymLinkOption("c", "s1.b", opt=boolopt)
descr = OptionDescription("opt", "", # descr = OptionDescription("opt", "",
[linkopt, OptionDescription("s1", "", [boolopt])]) # [linkopt, OptionDescription("s1", "", [boolopt])])
config = Config(descr) # config = Config(descr)
setattr(config, "s1.b", True) # setattr(config, "s1.b", True)
setattr(config, "s1.b", False) # setattr(config, "s1.b", False)
assert config.s1.b is False # assert config.s1.b is False
assert config.c is False # assert config.c is False
config.c = True # config.c = True
assert config.s1.b is True # assert config.s1.b is True
assert config.c is True # assert config.c is True
config.c = False # config.c = False
assert config.s1.b is False # assert config.s1.b is False
assert config.c is False # assert config.c is False
#
##____________________________________________________________ ##____________________________________________________________
#def test_config_impl_values(): #def test_config_impl_values():
# descr = make_description() # descr = make_description()
@ -401,8 +401,10 @@ def test_allow_multiple_changes_from_config():
config = Config(descr) config = Config(descr)
config.string = "oh" config.string = "oh"
assert config.string == "oh" assert config.string == "oh"
config.set(string2='blah') config.string = "blah"
assert config.bip.string2 == 'blah' assert config.string == "blah"
# config.set(string2='blah')
# assert config.bip.string2 == 'blah'
# ____________________________________________________________ # ____________________________________________________________

View File

@ -48,8 +48,10 @@ def test_optname_shall_not_start_with_numbers():
def test_option_has_an_api_name(): def test_option_has_an_api_name():
print "FIXME" raises(ValueError, "BoolOption('cfgimpl_get_settings', 'dummy', default=False)")
#gcdummy = BoolOption('cfgimpl_get_settings', 'dummy', default=False) raises(ValueError, "BoolOption('unwrap_from_path', 'dummy', default=False)")
#boolop = BoolOption('boolop', 'Test boolean option op', default=True) raises(ValueError, "BoolOption('objimpl_getdoc', 'dummy', default=False)")
#descr = OptionDescription('tiramisu', '', [gcdummy, boolop]) raises(ValueError, "BoolOption('_unvalid', 'dummy', default=False)")
#raises(ValueError, "cfg = Config(descr)") raises(ValueError, "BoolOption('6unvalid', 'dummy', default=False)")
BoolOption('unvalid6', 'dummy', default=False)
BoolOption('unvalid_', 'dummy', default=False)

View File

@ -27,13 +27,13 @@ def make_description():
master = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0]) master = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
interface1 = OptionDescription('interface1', '', [master]) interface1 = OptionDescription('interface1', '', [master])
interface1.set_group_type(groups.family) interface1.objimpl_set_group_type(groups.family)
general = OptionDescription('general', '', [numero_etab, nom_machine, general = OptionDescription('general', '', [numero_etab, nom_machine,
nombre_interfaces, activer_proxy_client, nombre_interfaces, activer_proxy_client,
mode_conteneur_actif, adresse_serveur_ntp, mode_conteneur_actif, adresse_serveur_ntp,
time_zone]) time_zone])
general.set_group_type(groups.family) general.objimpl_set_group_type(groups.family)
creole = OptionDescription('creole', 'first tiramisu configuration', [general, interface1]) creole = OptionDescription('creole', 'first tiramisu configuration', [general, interface1])
descr = OptionDescription('baseconfig', 'baseconifgdescr', [creole]) descr = OptionDescription('baseconfig', 'baseconifgdescr', [creole])
return descr return descr
@ -62,10 +62,10 @@ def test_get_group_type():
descr = make_description() descr = make_description()
config = Config(descr) config = Config(descr)
grp = config.unwrap_from_path('creole.general') grp = config.unwrap_from_path('creole.general')
assert grp.get_group_type() == groups.family assert grp.objimpl_get_group_type() == groups.family
assert grp.get_group_type() == 'family' assert grp.objimpl_get_group_type() == 'family'
assert isinstance(grp.get_group_type(), groups.GroupType) assert isinstance(grp.objimpl_get_group_type(), groups.GroupType)
raises(TypeError, 'grp.set_group_type(groups.default)') raises(TypeError, 'grp.objimpl_set_group_type(groups.default)')
def test_iter_on_groups(): def test_iter_on_groups():
@ -91,31 +91,31 @@ def test_groups_with_master():
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True) 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) 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 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
interface1.set_group_type(groups.master) interface1.objimpl_set_group_type(groups.master)
assert interface1.get_group_type() == groups.master assert interface1.objimpl_get_group_type() == groups.master
def test_groups_with_master_in_config(): def test_groups_with_master_in_config():
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True) 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) 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 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
interface1.set_group_type(groups.master) interface1.objimpl_set_group_type(groups.master)
Config(interface1) Config(interface1)
assert interface1.get_group_type() == groups.master assert interface1.objimpl_get_group_type() == groups.master
def test_allowed_groups(): def test_allowed_groups():
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True) 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) 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 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
raises(ValueError, "interface1.set_group_type('toto')") raises(ValueError, "interface1.objimpl_set_group_type('toto')")
def test_master_not_valid_name(): def test_master_not_valid_name():
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True) 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) 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 = OptionDescription('interface1', '', [ip_admin_eth0, netmask_admin_eth0])
raises(ValueError, "invalid_group.set_group_type(groups.master)") raises(ValueError, "invalid_group.objimpl_set_group_type(groups.master)")
def test_sub_group_in_master_group(): def test_sub_group_in_master_group():
@ -123,14 +123,14 @@ def test_sub_group_in_master_group():
netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True) netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True)
subgroup = OptionDescription("subgroup", '', []) subgroup = OptionDescription("subgroup", '', [])
invalid_group = OptionDescription('ip_admin_eth0', '', [subgroup, ip_admin_eth0, netmask_admin_eth0]) invalid_group = OptionDescription('ip_admin_eth0', '', [subgroup, ip_admin_eth0, netmask_admin_eth0])
raises(ValueError, "invalid_group.set_group_type(groups.master)") raises(ValueError, "invalid_group.objimpl_set_group_type(groups.master)")
def test_group_always_has_multis(): def test_group_always_has_multis():
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True) 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") netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau")
group = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0]) group = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
raises(ValueError, "group.set_group_type(groups.master)") raises(ValueError, "group.objimpl_set_group_type(groups.master)")
#____________________________________________________________ #____________________________________________________________
@ -138,13 +138,13 @@ def test_values_with_master_and_slaves():
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True) 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) 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 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
interface1.set_group_type(groups.master) interface1.objimpl_set_group_type(groups.master)
maconfig = OptionDescription('toto', '', [interface1]) maconfig = OptionDescription('toto', '', [interface1])
cfg = Config(maconfig) cfg = Config(maconfig)
opt = cfg.unwrap_from_path("ip_admin_eth0.ip_admin_eth0") opt = cfg.unwrap_from_path("ip_admin_eth0.ip_admin_eth0")
opt_slave = cfg.unwrap_from_path("ip_admin_eth0.netmask_admin_eth0") opt_slave = cfg.unwrap_from_path("ip_admin_eth0.netmask_admin_eth0")
owner = cfg._cfgimpl_context._cfgimpl_settings.getowner() owner = cfg._cfgimpl_context._cfgimpl_settings.getowner()
assert interface1.get_group_type() == groups.master assert interface1.objimpl_get_group_type() == groups.master
assert cfg.cfgimpl_get_values().getowner(opt) == owners.default assert cfg.cfgimpl_get_values().getowner(opt) == owners.default
assert cfg.cfgimpl_get_values().getowner(opt_slave) == owners.default assert cfg.cfgimpl_get_values().getowner(opt_slave) == owners.default
assert cfg.ip_admin_eth0.netmask_admin_eth0 == [] assert cfg.ip_admin_eth0.netmask_admin_eth0 == []
@ -159,13 +159,13 @@ def test_reset_values_with_master_and_slaves():
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True) 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) 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 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
interface1.set_group_type(groups.master) interface1.objimpl_set_group_type(groups.master)
maconfig = OptionDescription('toto', '', [interface1]) maconfig = OptionDescription('toto', '', [interface1])
cfg = Config(maconfig) cfg = Config(maconfig)
opt = cfg.unwrap_from_path("ip_admin_eth0.ip_admin_eth0") opt = cfg.unwrap_from_path("ip_admin_eth0.ip_admin_eth0")
opt_slave = cfg.unwrap_from_path("ip_admin_eth0.netmask_admin_eth0") opt_slave = cfg.unwrap_from_path("ip_admin_eth0.netmask_admin_eth0")
owner = cfg._cfgimpl_context._cfgimpl_settings.getowner() owner = cfg._cfgimpl_context._cfgimpl_settings.getowner()
assert interface1.get_group_type() == groups.master assert interface1.objimpl_get_group_type() == groups.master
assert cfg.cfgimpl_get_values().getowner(opt) == owners.default assert cfg.cfgimpl_get_values().getowner(opt) == owners.default
assert cfg.cfgimpl_get_values().getowner(opt_slave) == owners.default assert cfg.cfgimpl_get_values().getowner(opt_slave) == owners.default
cfg.ip_admin_eth0.ip_admin_eth0.append("192.168.230.145") cfg.ip_admin_eth0.ip_admin_eth0.append("192.168.230.145")
@ -182,7 +182,7 @@ def test_values_with_master_and_slaves_slave():
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True) 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) 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 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
interface1.set_group_type(groups.master) interface1.objimpl_set_group_type(groups.master)
maconfig = OptionDescription('toto', '', [interface1]) maconfig = OptionDescription('toto', '', [interface1])
cfg = Config(maconfig) cfg = Config(maconfig)
assert cfg.ip_admin_eth0.netmask_admin_eth0 == [] assert cfg.ip_admin_eth0.netmask_admin_eth0 == []
@ -204,7 +204,7 @@ def test_values_with_master_and_slaves_master():
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True) 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) 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 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
interface1.set_group_type(groups.master) interface1.objimpl_set_group_type(groups.master)
maconfig = OptionDescription('toto', '', [interface1]) maconfig = OptionDescription('toto', '', [interface1])
cfg = Config(maconfig) cfg = Config(maconfig)
cfg.ip_admin_eth0.ip_admin_eth0.append("192.168.230.145") cfg.ip_admin_eth0.ip_admin_eth0.append("192.168.230.145")

View File

@ -21,7 +21,7 @@
# the whole pypy projet is under MIT licence # the whole pypy projet is under MIT licence
# ____________________________________________________________ # ____________________________________________________________
#from inspect import getmembers, ismethod #from inspect import getmembers, ismethod
from tiramisu.error import PropertiesOptionError, ConflictOptionError from tiramisu.error import PropertiesOptionError
from tiramisu.option import OptionDescription, Option, SymLinkOption from tiramisu.option import OptionDescription, Option, SymLinkOption
from tiramisu.setting import groups, Setting from tiramisu.setting import groups, Setting
from tiramisu.value import Values from tiramisu.value import Values
@ -84,7 +84,7 @@ class SubConfig(object):
self.cfgimpl_get_values().setitem(child, value, self.cfgimpl_get_values().setitem(child, value,
force_permissive=force_permissive) force_permissive=force_permissive)
else: else:
child.setoption(self.cfgimpl_get_context(), value) child._setoption(self.cfgimpl_get_context(), value)
def __delattr__(self, name): def __delattr__(self, name):
child = getattr(self._cfgimpl_descr, name) child = getattr(self._cfgimpl_descr, name)
@ -114,11 +114,11 @@ class SubConfig(object):
if name.startswith('_cfgimpl_') or name.startswith('cfgimpl_'): if name.startswith('_cfgimpl_') or name.startswith('cfgimpl_'):
# if it were in __dict__ it would have been found already # if it were in __dict__ it would have been found already
object.__getattr__(self, name) object.__getattr__(self, name)
opt_or_descr = getattr(self._cfgimpl_descr, name) opt_or_descr = getattr(self.cfgimpl_get_description(), name)
# symlink options # symlink options
if isinstance(opt_or_descr, SymLinkOption): if isinstance(opt_or_descr, SymLinkOption):
rootconfig = self.cfgimpl_get_context() rootconfig = self.cfgimpl_get_context()
path = rootconfig.cfgimpl_get_description().get_path_by_opt(opt_or_descr.opt) path = rootconfig.cfgimpl_get_description().objimpl_get_path_by_opt(opt_or_descr.opt)
return rootconfig._getattr(path, validate=validate, return rootconfig._getattr(path, validate=validate,
force_properties=force_properties, force_properties=force_properties,
force_permissive=force_permissive) force_permissive=force_permissive)
@ -127,12 +127,6 @@ class SubConfig(object):
True, False, True, False,
force_permissive=force_permissive, force_permissive=force_permissive,
force_properties=force_properties) force_properties=force_properties)
children = self.cfgimpl_get_description()._children
if opt_or_descr not in children[1]:
raise AttributeError(_("{0} with name {1} object has "
"no attribute {2}").format(self.__class__,
opt_or_descr._name,
name))
return SubConfig(opt_or_descr, self._cfgimpl_context) return SubConfig(opt_or_descr, self._cfgimpl_context)
else: else:
return self.cfgimpl_get_values().getitem(opt_or_descr, return self.cfgimpl_get_values().getitem(opt_or_descr,
@ -149,27 +143,27 @@ class SubConfig(object):
force_properties=force_properties) force_properties=force_properties)
return self, path[-1] return self, path[-1]
def getkey(self):
return self._cfgimpl_descr.getkey(self)
def __hash__(self): def __hash__(self):
return hash(self.getkey()) return hash(self.cfgimpl_get_description().objimpl_getkey(self))
def __eq__(self, other): def __eq__(self, other):
"Config comparison" "Config comparison"
if not isinstance(other, Config): if not isinstance(other, Config):
return False return False
return self.getkey() == other.getkey() return self.cfgimpl_get_description().objimpl_getkey(self) == \
other.cfgimpl_get_description().objimpl_getkey(other)
def __ne__(self, other): def __ne__(self, other):
"Config comparison" "Config comparison"
if not isinstance(other, Config):
return False
return not self == other return not self == other
# ______________________________________________________________________ # ______________________________________________________________________
def __iter__(self): def __iter__(self):
"""Pythonesque way of parsing group's ordered options. """Pythonesque way of parsing group's ordered options.
iteration only on Options (not OptionDescriptions)""" iteration only on Options (not OptionDescriptions)"""
for child in self._cfgimpl_descr._children[1]: for child in self.cfgimpl_get_description().objimpl_getchildren():
if not isinstance(child, OptionDescription): if not isinstance(child, OptionDescription):
try: try:
yield child._name, getattr(self, child._name) yield child._name, getattr(self, child._name)
@ -181,7 +175,7 @@ class SubConfig(object):
def iter_all(self): def iter_all(self):
"""A way of parsing options **and** groups. """A way of parsing options **and** groups.
iteration on Options and OptionDescriptions.""" iteration on Options and OptionDescriptions."""
for child in self._cfgimpl_descr._children[1]: for child in self.cfgimpl_get_description().objimpl_getchildren():
try: try:
yield child._name, getattr(self, child._name) yield child._name, getattr(self, child._name)
except GeneratorExit: except GeneratorExit:
@ -202,13 +196,11 @@ class SubConfig(object):
if group_type is not None: if group_type is not None:
if not isinstance(group_type, groups.GroupType): if not isinstance(group_type, groups.GroupType):
raise TypeError(_("unknown group_type: {0}").format(group_type)) raise TypeError(_("unknown group_type: {0}").format(group_type))
for child in self._cfgimpl_descr._children[1]: for child in self.cfgimpl_get_description().objimpl_getchildren():
if isinstance(child, OptionDescription): if isinstance(child, OptionDescription):
try: try:
if group_type is not None: if group_type is None or (group_type is not None and
if child.get_group_type() == group_type: child.objimpl_get_group_type() == group_type):
yield child._name, getattr(self, child._name)
else:
yield child._name, getattr(self, child._name) yield child._name, getattr(self, child._name)
except GeneratorExit: except GeneratorExit:
raise StopIteration raise StopIteration
@ -230,31 +222,10 @@ class SubConfig(object):
__repr__ = __str__ __repr__ = __str__
def getpaths(self, include_groups=False, allpaths=False): def cfgimpl_get_path(self):
"""returns a list of all paths in self, recursively, taking care of
the context of properties (hidden/disabled)
:param include_groups: if true, OptionDescription are included
:param allpaths: all the options (event the properties protected ones)
:returns: list of all paths
"""
paths = []
for path in self._cfgimpl_descr.getpaths(include_groups=include_groups):
if allpaths:
paths.append(path)
else:
try:
getattr(self, path)
except PropertiesOptionError:
pass
else:
paths.append(path)
return paths
def getpath(self):
descr = self.cfgimpl_get_description() descr = self.cfgimpl_get_description()
context_descr = self.cfgimpl_get_context().cfgimpl_get_description() context_descr = self.cfgimpl_get_context().cfgimpl_get_description()
return context_descr.get_path_by_opt(descr) return context_descr.objimpl_get_path_by_opt(descr)
def find(self, bytype=None, byname=None, byvalue=None, type_='option'): def find(self, bytype=None, byname=None, byvalue=None, type_='option'):
""" """
@ -268,7 +239,7 @@ class SubConfig(object):
return self.cfgimpl_get_context()._find(bytype, byname, byvalue, return self.cfgimpl_get_context()._find(bytype, byname, byvalue,
first=False, first=False,
type_=type_, type_=type_,
_subpath=self.getpath()) _subpath=self.cfgimpl_get_path())
def find_first(self, bytype=None, byname=None, byvalue=None, type_='option'): def find_first(self, bytype=None, byname=None, byvalue=None, type_='option'):
""" """
@ -282,7 +253,7 @@ class SubConfig(object):
return self.cfgimpl_get_context()._find(bytype, byname, byvalue, return self.cfgimpl_get_context()._find(bytype, byname, byvalue,
first=True, first=True,
type_=type_, type_=type_,
_subpath=self.getpath()) _subpath=self.cfgimpl_get_path())
def make_dict(self, flatten=False, _currpath=None, withoption=None, withvalue=None): def make_dict(self, flatten=False, _currpath=None, withoption=None, withvalue=None):
"""export the whole config into a `dict` """export the whole config into a `dict`
@ -293,7 +264,7 @@ class SubConfig(object):
if withoption is None and withvalue is not None: if withoption is None and withvalue is not None:
raise ValueError(_("make_dict can't filtering with value without option")) raise ValueError(_("make_dict can't filtering with value without option"))
if withoption is not None: if withoption is not None:
mypath = self.getpath() mypath = self.cfgimpl_get_path()
for path in self.cfgimpl_get_context()._find(bytype=Option, for path in self.cfgimpl_get_context()._find(bytype=Option,
byname=withoption, byname=withoption,
byvalue=withvalue, byvalue=withvalue,
@ -301,7 +272,7 @@ class SubConfig(object):
type_='path', type_='path',
_subpath=mypath): _subpath=mypath):
path = '.'.join(path.split('.')[:-1]) path = '.'.join(path.split('.')[:-1])
opt = self.cfgimpl_get_context().cfgimpl_get_description().get_opt_by_path(path) opt = self.cfgimpl_get_context().cfgimpl_get_description().objimpl_get_opt_by_path(path)
if mypath is not None: if mypath is not None:
if mypath == path: if mypath == path:
withoption = None withoption = None
@ -316,7 +287,7 @@ class SubConfig(object):
self._make_sub_dict(opt, path, pathsvalues, _currpath, flatten) self._make_sub_dict(opt, path, pathsvalues, _currpath, flatten)
#withoption can be set to None below ! #withoption can be set to None below !
if withoption is None: if withoption is None:
for opt in self.cfgimpl_get_description().getchildren(): for opt in self.cfgimpl_get_description().objimpl_getchildren():
path = opt._name path = opt._name
self._make_sub_dict(opt, path, pathsvalues, _currpath, flatten) self._make_sub_dict(opt, path, pathsvalues, _currpath, flatten)
if _currpath == []: if _currpath == []:
@ -359,7 +330,7 @@ class Config(SubConfig):
self._cfgimpl_build_all_paths() self._cfgimpl_build_all_paths()
def _cfgimpl_build_all_paths(self): def _cfgimpl_build_all_paths(self):
self._cfgimpl_descr.build_cache() self._cfgimpl_descr.objimpl_build_cache()
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: if 'values' in only:
@ -379,38 +350,7 @@ class Config(SubConfig):
return getattr(homeconfig._cfgimpl_descr, path) return getattr(homeconfig._cfgimpl_descr, path)
return getattr(self._cfgimpl_descr, path) return getattr(self._cfgimpl_descr, path)
def set(self, **kwargs): def cfgimpl_get_path(self):
"""
do what I mean"-interface to option setting. Searches all paths
starting from that config for matches of the optional arguments
and sets the found option if the match is not ambiguous.
:param kwargs: dict of name strings to values.
"""
#opts, paths = self.cfgimpl_get_description()._cache_paths
all_paths = [p.split(".") for p in self.getpaths(allpaths=True)]
for key, value in kwargs.iteritems():
key_p = key.split('.')
candidates = [p for p in all_paths if p[-len(key_p):] == key_p]
if len(candidates) == 1:
name = '.'.join(candidates[0])
homeconfig, name = self.cfgimpl_get_home_by_path(name)
getattr(homeconfig, name)
#except MandatoryError:
# pass
#except PropertiesOptionError, e:
# raise e # HiddenOptionError or DisabledOptionError
child = getattr(homeconfig._cfgimpl_descr, name)
self.cfgimpl_get_values()[child] = value
elif len(candidates) > 1:
raise ConflictOptionError(
_('more than one option that ends with {}').format(key))
else:
raise AttributeError(
_('there is no option that matches {}'
' or the option is hidden or disabled').format(key))
def getpath(self):
return None return None
def _find(self, bytype, byname, byvalue, first, type_='option', def _find(self, bytype, byname, byvalue, first, type_='option',
@ -506,7 +446,7 @@ def mandatory_warnings(config):
""" """
#if value in cache, properties are not calculated #if value in cache, properties are not calculated
config.cfgimpl_reset_cache(only=('values',)) config.cfgimpl_reset_cache(only=('values',))
for path in config.cfgimpl_get_description().getpaths(include_groups=True): for path in config.cfgimpl_get_description().objimpl_getpaths(include_groups=True):
try: try:
config._getattr(path, force_properties=('mandatory',)) config._getattr(path, force_properties=('mandatory',))
except PropertiesOptionError, err: except PropertiesOptionError, err:

View File

@ -37,11 +37,6 @@ class PropertiesOptionError(AttributeError):
super(PropertiesOptionError, self).__init__(msg) super(PropertiesOptionError, self).__init__(msg)
class ConflictOptionError(StandardError):
"more than one option"
pass
#____________config___________ #____________config___________
class ConfigError(StandardError): class ConfigError(StandardError):
"""try to change owner for an option without value """try to change owner for an option without value

View File

@ -30,6 +30,8 @@ from tiramisu.setting import groups, multitypes
from tiramisu.i18n import _ from tiramisu.i18n import _
name_regexp = re.compile(r'^\d+') name_regexp = re.compile(r'^\d+')
forbidden_names = ['iter_all', 'iter_group', 'find', 'find_fisrt',
'make_dict', 'unwrap_from_path']
def valid_name(name): def valid_name(name):
@ -37,7 +39,10 @@ def valid_name(name):
name = str(name) name = str(name)
except: except:
return False return False
if re.match(name_regexp, name) is None: if re.match(name_regexp, name) is None and not name.startswith('_') \
and name not in forbidden_names \
and not name.startswith('objimpl_') and \
not name.startswith('cfgimpl_'):
return True return True
else: else:
return False return False
@ -48,7 +53,7 @@ def valid_name(name):
class BaseInformation(object): class BaseInformation(object):
__slots__ = ('_informations') __slots__ = ('_informations')
def set_information(self, key, value): def objimpl_set_information(self, key, value):
"""updates the information's attribute """updates the information's attribute
(wich is a dictionnary) (wich is a dictionnary)
@ -57,7 +62,7 @@ class BaseInformation(object):
""" """
self._informations[key] = value self._informations[key] = value
def get_information(self, key, default=None): def objimpl_get_information(self, key, default=None):
"""retrieves one information's item """retrieves one information's item
:param key: the item string (ex: "help") :param key: the item string (ex: "help")
@ -85,7 +90,6 @@ class Option(BaseInformation):
requires=None, multi=False, callback=None, requires=None, multi=False, callback=None,
callback_params=None, validator=None, validator_args=None, callback_params=None, validator=None, validator_args=None,
properties=None): properties=None):
#FIXME : validation de callback et callback_params !!!
""" """
:param name: the option's name :param name: the option's name
:param doc: the option's description :param doc: the option's description
@ -107,7 +111,7 @@ class Option(BaseInformation):
raise ValueError(_("invalid name: {0} for option").format(name)) raise ValueError(_("invalid name: {0} for option").format(name))
self._name = name self._name = name
self._informations = {} self._informations = {}
self.set_information('doc', doc) self.objimpl_set_information('doc', doc)
validate_requires_arg(requires, self._name) validate_requires_arg(requires, self._name)
self._requires = requires self._requires = requires
self._multi = multi self._multi = multi
@ -133,6 +137,11 @@ class Option(BaseInformation):
raise ValueError(_("params defined for a callback function but " 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 callback is not None:
if not isinstance(callback, str):
raise ValueError('callback must be a string')
if callback_params is not None and \
not isinstance(callback_params, dict):
raise ValueError('callback_params must be a dict')
self._callback = (callback, callback_params) self._callback = (callback, callback_params)
else: else:
self._callback = None self._callback = None
@ -143,14 +152,14 @@ class Option(BaseInformation):
# raise ValidateError("invalid default value {0} " # raise ValidateError("invalid default value {0} "
# "for option {1} : not list type" # "for option {1} : not list type"
# "".format(str(default), name)) # "".format(str(default), name))
if not self.validate(default): if not self.objimpl_validate(default):
raise ValueError(_("invalid default value {0} " raise ValueError(_("invalid default value {0} "
"for option {1}" "for option {1}"
"").format(str(default), name)) "").format(str(default), name))
self._multitype = multitypes.default self._multitype = multitypes.default
self._default_multi = default_multi self._default_multi = default_multi
else: else:
if default is not None and not self.validate(default): if default is not None and not self.objimpl_validate(default):
raise ValueError(_("invalid default value {0} " raise ValueError(_("invalid default value {0} "
"for option {1}").format(str(default), name)) "for option {1}").format(str(default), name))
self._default = default self._default = default
@ -161,7 +170,7 @@ class Option(BaseInformation):
' must be a tuple').format(type(properties), self._name)) ' must be a tuple').format(type(properties), self._name))
self._properties = properties # 'hidden', 'disabled'... self._properties = properties # 'hidden', 'disabled'...
def validate(self, value, context=None, validate=True): def objimpl_validate(self, value, context=None, validate=True):
""" """
:param value: the option's value :param value: the option's value
:param validate: if true enables ``self._validator`` validation :param validate: if true enables ``self._validator`` validation
@ -181,7 +190,7 @@ class Option(BaseInformation):
if not self._validate(value): if not self._validate(value):
return False return False
if cons is not None: if cons is not None:
return cons.valid_consistency(self, value, context, None) return cons._valid_consistency(self, value, context, None)
else: else:
if not isinstance(value, list): if not isinstance(value, list):
raise ValueError(_("invalid value {0} " raise ValueError(_("invalid value {0} "
@ -197,52 +206,52 @@ class Option(BaseInformation):
return False return False
if not self._validate(val): if not self._validate(val):
return False return False
if cons is not None and not cons.valid_consistency(self, val, context, index): if cons is not None and not cons._valid_consistency(self, val, context, index):
return False return False
return True return True
def getdefault(self, default_multi=False): def objimpl_getdefault(self, default_multi=False):
"accessing the default value" "accessing the default value"
if not default_multi or not self.is_multi(): if not default_multi or not self.objimpl_is_multi():
return self._default return self._default
else: else:
return self.getdefault_multi() return self.getdefault_multi()
def getdefault_multi(self): def objimpl_getdefault_multi(self):
"accessing the default value for a multi" "accessing the default value for a multi"
return self._default_multi return self._default_multi
def get_multitype(self): def objimpl_get_multitype(self):
return self._multitype return self._multitype
def get_master_slaves(self): def objimpl_get_master_slaves(self):
return self._master_slaves return self._master_slaves
def is_empty_by_default(self): def objimpl_is_empty_by_default(self):
"no default value has been set yet" "no default value has been set yet"
if ((not self.is_multi() and self._default is None) or if ((not self.objimpl_is_multi() and self._default is None) or
(self.is_multi() and (self._default == [] or None in self._default))): (self.objimpl_is_multi() and (self._default == [] or None in self._default))):
return True return True
return False return False
def getdoc(self): def objimpl_getdoc(self):
"accesses the Option's doc" "accesses the Option's doc"
return self.get_information('doc') return self.objimpl_get_information('doc')
def has_callback(self): def objimpl_has_callback(self):
"to know if a callback has been defined or not" "to know if a callback has been defined or not"
if self._callback is None: if self._callback is None:
return False return False
else: else:
return True return True
def getkey(self, value): def objimpl_getkey(self, value):
return value return value
def is_multi(self): def objimpl_is_multi(self):
return self._multi return self._multi
def add_consistency(self, func, opts): def objimpl_add_consistency(self, func, opts):
pass pass
if self._consistencies is None: if self._consistencies is None:
self._consistencies = [] self._consistencies = []
@ -250,14 +259,14 @@ class Option(BaseInformation):
opts = list(opts) opts = list(opts)
opts.append(self) opts.append(self)
opts = tuple(opts) opts = tuple(opts)
self._consistencies.append(('cons_{}'.format(func), opts)) self._consistencies.append(('_cons_{}'.format(func), opts))
def cons_not_equal(self, opt, value, context, index, opts): def _cons_not_equal(self, opt, value, context, index, opts):
values = [value] values = [value]
descr = context.cfgimpl_get_description() descr = context.cfgimpl_get_description()
for opt_ in opts: for opt_ in opts:
if opt_ is not opt: if opt_ is not opt:
path = descr.get_path_by_opt(opt_) path = descr.objimpl_get_path_by_opt(opt_)
val = context._getattr(path, validate=False) val = context._getattr(path, validate=False)
if val is not None: if val is not None:
if val in values: if val in values:
@ -265,7 +274,7 @@ class Option(BaseInformation):
values.append(val) values.append(val)
return True return True
def cons_lower(self, value): def _cons_lower(self, value):
try: try:
return value.islower() return value.islower()
except AttributeError: except AttributeError:
@ -274,8 +283,8 @@ class Option(BaseInformation):
class ChoiceOption(Option): class ChoiceOption(Option):
__slots__ = ('_values', '_open_values', 'opt_type') __slots__ = ('_values', '_open_values', '_opt_type')
opt_type = 'string' _opt_type = 'string'
def __init__(self, name, doc, values, default=None, default_multi=None, def __init__(self, name, doc, values, default=None, default_multi=None,
requires=None, multi=False, callback=None, requires=None, multi=False, callback=None,
@ -306,40 +315,40 @@ class ChoiceOption(Option):
class BoolOption(Option): class BoolOption(Option):
__slots__ = ('opt_type') __slots__ = ('_opt_type')
opt_type = 'bool' _opt_type = 'bool'
def _validate(self, value): def _validate(self, value):
return isinstance(value, bool) return isinstance(value, bool)
class IntOption(Option): class IntOption(Option):
__slots__ = ('opt_type') __slots__ = ('_opt_type')
opt_type = 'int' _opt_type = 'int'
def _validate(self, value): def _validate(self, value):
return isinstance(value, int) return isinstance(value, int)
class FloatOption(Option): class FloatOption(Option):
__slots__ = ('opt_type') __slots__ = ('_opt_type')
opt_type = 'float' _opt_type = 'float'
def _validate(self, value): def _validate(self, value):
return isinstance(value, float) return isinstance(value, float)
class StrOption(Option): class StrOption(Option):
__slots__ = ('opt_type') __slots__ = ('_opt_type')
opt_type = 'string' _opt_type = 'string'
def _validate(self, value): def _validate(self, value):
return isinstance(value, str) return isinstance(value, str)
class UnicodeOption(Option): class UnicodeOption(Option):
__slots__ = ('opt_type') __slots__ = ('_opt_type')
opt_type = 'unicode' _opt_type = 'unicode'
_empty = u'' _empty = u''
def _validate(self, value): def _validate(self, value):
@ -347,30 +356,30 @@ class UnicodeOption(Option):
class SymLinkOption(object): class SymLinkOption(object):
__slots__ = ('_name', 'opt', '_consistencies') __slots__ = ('_name', '_opt', '_consistencies')
opt_type = 'symlink' _opt_type = 'symlink'
_consistencies = None _consistencies = None
def __init__(self, name, path, opt): def __init__(self, name, path, opt):
self._name = name self._name = name
self.opt = opt self._opt = opt
def setoption(self, context, value): def _setoption(self, context, value):
path = context.cfgimpl_get_description().get_path_by_opt(self.opt) path = context.cfgimpl_get_description().objimpl_get_path_by_opt(self._opt)
setattr(context, path, value) setattr(context, path, value)
def __getattr__(self, name): def __getattr__(self, name):
if name in ('_name', 'opt', 'setoption'): if name in ('_name', '_opt', '_setoption', '_consistencies'):
return object.__gettattr__(self, name) return object.__gettattr__(self, name)
else: else:
return getattr(self.opt, name) return getattr(self._opt, name)
class IPOption(Option): class IPOption(Option):
__slots__ = ('opt_type', '_only_private') __slots__ = ('_opt_type', '_only_private')
opt_type = 'ip' _opt_type = 'ip'
def set_private(self): def objimpl_set_private(self):
self._only_private = True self._only_private = True
def _validate(self, value): def _validate(self, value):
@ -388,8 +397,8 @@ class IPOption(Option):
class NetworkOption(Option): class NetworkOption(Option):
__slots__ = ('opt_type') __slots__ = ('_opt_type')
opt_type = 'network' _opt_type = 'network'
def _validate(self, value): def _validate(self, value):
try: try:
@ -400,8 +409,8 @@ class NetworkOption(Option):
class NetmaskOption(Option): class NetmaskOption(Option):
__slots__ = ('opt_type') __slots__ = ('_opt_type')
opt_type = 'netmask' _opt_type = 'netmask'
def __init__(self, name, doc, default=None, default_multi=None, def __init__(self, name, doc, default=None, default_multi=None,
requires=None, multi=False, callback=None, requires=None, multi=False, callback=None,
@ -435,30 +444,30 @@ 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, opt, value, context, index, opts):
#opts must be (netmask, network) options #opts must be (netmask, network) options
return self._cons_netmask(opt, value, context, index, opts, False) return self._cons_netmask(opt, value, context, index, opts, False)
def cons_ip_netmask(self, opt, value, context, index, opts): def _cons_ip_netmask(self, opt, value, context, index, opts):
#opts must be (netmask, ip) options #opts must be (netmask, ip) options
return self._cons_netmask(opt, value, context, index, opts, True) return self._cons_netmask(opt, value, context, index, opts, 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 opt_netmask, opt_ipnetwork = opts
descr = context.cfgimpl_get_description() descr = context.cfgimpl_get_description()
if opt is opt_ipnetwork: if opt is opt_ipnetwork:
val_ipnetwork = value val_ipnetwork = value
path = descr.get_path_by_opt(opt_netmask) path = descr.objimpl_get_path_by_opt(opt_netmask)
val_netmask = context._getattr(path, validate=False) val_netmask = context._getattr(path, validate=False)
if opt_netmask.is_multi(): if opt_netmask.objimpl_is_multi():
val_netmask = val_netmask[index] val_netmask = val_netmask[index]
if val_netmask is None: if val_netmask is None:
return True return True
else: else:
val_netmask = value val_netmask = value
path = descr.get_path_by_opt(opt_ipnetwork) path = descr.objimpl_get_path_by_opt(opt_ipnetwork)
val_ipnetwork = getattr(context, path) val_ipnetwork = getattr(context, path)
if opt_ipnetwork.is_multi(): if opt_ipnetwork.objimpl_is_multi():
val_ipnetwork = val_ipnetwork[index] val_ipnetwork = val_ipnetwork[index]
if val_ipnetwork is None: if val_ipnetwork is None:
return True return True
@ -470,8 +479,8 @@ class NetmaskOption(Option):
class DomainnameOption(Option): class DomainnameOption(Option):
__slots__ = ('opt_type', '_type', '_allow_ip') __slots__ = ('_opt_type', '_type', '_allow_ip')
opt_type = 'domainname' _opt_type = 'domainname'
#allow_ip #allow_ip
def __init__(self, name, doc, default=None, default_multi=None, def __init__(self, name, doc, default=None, default_multi=None,
@ -531,7 +540,7 @@ class OptionDescription(BaseInformation):
raise ValueError(_("invalid name: {0} for option descr").format(name)) raise ValueError(_("invalid name: {0} for option descr").format(name))
self._name = name self._name = name
self._informations = {} self._informations = {}
self.set_information('doc', doc) self.objimpl_set_information('doc', doc)
child_names = [child._name for child in children] child_names = [child._name for child in children]
#better performance like this #better performance like this
valid_child = copy(child_names) valid_child = copy(child_names)
@ -554,8 +563,8 @@ class OptionDescription(BaseInformation):
# the group_type is useful for filtering OptionDescriptions in a config # the group_type is useful for filtering OptionDescriptions in a config
self._group_type = groups.default self._group_type = groups.default
def getdoc(self): def objimpl_getdoc(self):
return self.get_information('doc') return self.objimpl_get_information('doc')
def __getattr__(self, name): def __getattr__(self, name):
try: try:
@ -564,33 +573,32 @@ class OptionDescription(BaseInformation):
raise AttributeError(_('unknown Option {} in OptionDescription {}' raise AttributeError(_('unknown Option {} in OptionDescription {}'
'').format(name, self._name)) '').format(name, self._name))
def getkey(self, config): def objimpl_getkey(self, config):
return tuple([child.getkey(getattr(config, child._name)) return tuple([child.objimpl_getkey(getattr(config, child._name))
for child in self._children[1]]) for child in self.objimpl_getchildren()])
def getpaths(self, include_groups=False, _currpath=None): def objimpl_getpaths(self, include_groups=False, _currpath=None):
"""returns a list of all paths in self, recursively """returns a list of all paths in self, recursively
_currpath should not be provided (helps with recursion) _currpath should not be provided (helps with recursion)
""" """
#FIXME : cache
if _currpath is None: if _currpath is None:
_currpath = [] _currpath = []
paths = [] paths = []
for option in self._children[1]: for option in self.objimpl_getchildren():
attr = option._name attr = option._name
if isinstance(option, OptionDescription): if isinstance(option, OptionDescription):
if include_groups: if include_groups:
paths.append('.'.join(_currpath + [attr])) paths.append('.'.join(_currpath + [attr]))
paths += option.getpaths(include_groups=include_groups, paths += option.objimpl_getpaths(include_groups=include_groups,
_currpath=_currpath + [attr]) _currpath=_currpath + [attr])
else: else:
paths.append('.'.join(_currpath + [attr])) paths.append('.'.join(_currpath + [attr]))
return paths return paths
def getchildren(self): def objimpl_getchildren(self):
return self._children[1] return self._children[1]
def build_cache(self, cache_path=None, cache_option=None, _currpath=None, _consistencies=None): def objimpl_build_cache(self, cache_path=None, cache_option=None, _currpath=None, _consistencies=None):
if _currpath is None and self._cache_paths is not None: if _currpath is None and self._cache_paths is not None:
return return
if _currpath is None: if _currpath is None:
@ -602,7 +610,7 @@ class OptionDescription(BaseInformation):
if cache_path is None: if cache_path is None:
cache_path = [self._name] cache_path = [self._name]
cache_option = [self] cache_option = [self]
for option in self._children[1]: for option in self.objimpl_getchildren():
attr = option._name attr = option._name
if attr.startswith('_cfgimpl'): if attr.startswith('_cfgimpl'):
continue continue
@ -616,7 +624,7 @@ class OptionDescription(BaseInformation):
_consistencies.setdefault(opt, []).append((func, opts)) _consistencies.setdefault(opt, []).append((func, opts))
else: else:
_currpath.append(attr) _currpath.append(attr)
option.build_cache(cache_path, cache_option, _currpath, _consistencies) option.objimpl_build_cache(cache_path, cache_option, _currpath, _consistencies)
_currpath.pop() _currpath.pop()
if save: if save:
#valid no duplicated option #valid no duplicated option
@ -631,20 +639,20 @@ class OptionDescription(BaseInformation):
self._cache_paths = (tuple(cache_option), tuple(cache_path)) self._cache_paths = (tuple(cache_option), tuple(cache_path))
self._consistencies = _consistencies self._consistencies = _consistencies
def get_opt_by_path(self, path): def obgimpl_get_opt_by_path(self, path):
try: try:
return self._cache_paths[0][self._cache_paths[1].index(path)] return self._cache_paths[0][self._cache_paths[1].index(path)]
except ValueError: except ValueError:
raise AttributeError(_('no option for path {}').format(path)) raise AttributeError(_('no option for path {}').format(path))
def get_path_by_opt(self, opt): def objimpl_get_path_by_opt(self, opt):
try: try:
return self._cache_paths[1][self._cache_paths[0].index(opt)] return self._cache_paths[1][self._cache_paths[0].index(opt)]
except ValueError: except ValueError:
raise AttributeError(_('no option {} found').format(opt)) raise AttributeError(_('no option {} found').format(opt))
# ____________________________________________________________ # ____________________________________________________________
def set_group_type(self, group_type): def objimpl_set_group_type(self, group_type):
"""sets a given group object to an OptionDescription """sets a given group object to an OptionDescription
:param group_type: an instance of `GroupType` or `MasterGroupType` :param group_type: an instance of `GroupType` or `MasterGroupType`
@ -661,11 +669,11 @@ class OptionDescription(BaseInformation):
#for collect all slaves #for collect all slaves
slaves = [] slaves = []
master = None master = None
for child in self._children[1]: for child in self.objimpl_getchildren():
if isinstance(child, OptionDescription): if isinstance(child, OptionDescription):
raise ValueError(_("master group {} shall not have " raise ValueError(_("master group {} shall not have "
"a subgroup").format(self._name)) "a subgroup").format(self._name))
if not child.is_multi(): if not child.objimpl_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" ": this option is not a multi"
"").format(child._name, self._name)) "").format(child._name, self._name))
@ -679,7 +687,7 @@ class OptionDescription(BaseInformation):
raise ValueError(_('master group with wrong master name for {}' raise ValueError(_('master group with wrong master name for {}'
'').format(self._name)) '').format(self._name))
master._master_slaves = tuple(slaves) master._master_slaves = tuple(slaves)
for child in self._children[1]: for child in self.objimpl_getchildren():
if child != master: if child != master:
child._master_slaves = master child._master_slaves = master
child._multitype = multitypes.slave child._multitype = multitypes.slave
@ -689,10 +697,10 @@ class OptionDescription(BaseInformation):
else: else:
raise ValueError(_('not allowed group_type : {0}').format(group_type)) raise ValueError(_('not allowed group_type : {0}').format(group_type))
def get_group_type(self): def objimpl_get_group_type(self):
return self._group_type return self._group_type
def valid_consistency(self, opt, value, context, index): def _valid_consistency(self, opt, value, context, index):
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:

View File

@ -26,6 +26,10 @@ from tiramisu.i18n import _
expires_time = 5 expires_time = 5
ro_remove = ('permissive', 'hidden')
ro_append = ('frozen', 'disabled', 'validator', 'everything_frozen', 'mandatory')
rw_remove = ('permissive', 'everything_frozen', 'mandatory')
rw_append = ('frozen', 'disabled', 'validator', 'hidden')
class _const: class _const:
@ -303,25 +307,19 @@ class Setting(object):
return self._owner return self._owner
#____________________________________________________________ #____________________________________________________________
def _read(self, remove, append):
for prop in remove:
self.remove(prop)
for prop in append:
self.append(prop)
def read_only(self): def read_only(self):
"convenience method to freeze, hidde and disable" "convenience method to freeze, hidde and disable"
self.append('everything_frozen') self._read(ro_remove, ro_append)
self.append('frozen') # can be usefull...
self.remove('hidden')
self.append('disabled')
self.append('mandatory')
self.append('validator')
self.remove('permissive')
def read_write(self): def read_write(self):
"convenience method to freeze, hidde and disable" "convenience method to freeze, hidde and disable"
self.remove('everything_frozen') self._read(rw_remove, rw_append)
self.append('frozen') # can be usefull...
self.append('hidden')
self.append('disabled')
self.remove('mandatory')
self.append('validator')
self.remove('permissive')
def _set_cache(self, opt, props): def _set_cache(self, opt, props):
if 'expire' in self: if 'expire' in self:
@ -355,7 +353,7 @@ def apply_requires(opt, config):
settings = config.cfgimpl_get_settings() settings = config.cfgimpl_get_settings()
setting = Property(settings, settings._get_properties(opt, False), opt) setting = Property(settings, settings._get_properties(opt, False), opt)
trigger_actions = build_actions(opt._requires) trigger_actions = build_actions(opt._requires)
optpath = config.cfgimpl_get_context().cfgimpl_get_description().get_path_by_opt(opt) optpath = config.cfgimpl_get_context().cfgimpl_get_description().objimpl_get_path_by_opt(opt)
for requires in trigger_actions.values(): for requires in trigger_actions.values():
matches = False matches = False
for require in requires: for require in requires:

View File

@ -43,8 +43,8 @@ class Values(object):
"return value or default value if not set" "return value or default value if not set"
#if no value #if no value
if opt not in self._values: if opt not in self._values:
value = opt.getdefault() value = opt.objimpl_getdefault()
if opt.is_multi(): if opt.objimpl_is_multi():
value = Multi(value, self.context, opt) value = Multi(value, self.context, opt)
else: else:
#if value #if value
@ -62,11 +62,11 @@ class Values(object):
def _is_empty(self, opt, value): def _is_empty(self, opt, value):
"convenience method to know if an option is empty" "convenience method to know if an option is empty"
empty = opt._empty empty = opt._empty
if (not opt.is_multi() and (value is None or value == empty)) or \ if (not opt.objimpl_is_multi() and (value is None or value == empty)) or \
(opt.is_multi() and (value == [] or (opt.objimpl_is_multi() and (value == [] or
None in value or empty in value)): None in value or empty in value)):
return True return True
if self.is_default_owner(opt) and opt.is_empty_by_default(): if self.is_default_owner(opt) and opt.objimpl_is_empty_by_default():
return True return True
return False return False
@ -97,7 +97,7 @@ class Values(object):
setting = self.context.cfgimpl_get_settings() setting = self.context.cfgimpl_get_settings()
value = self._get_value(opt) value = self._get_value(opt)
is_frozen = 'frozen' in setting[opt] is_frozen = 'frozen' in setting[opt]
if opt.has_callback(): if opt.objimpl_has_callback():
#if value is set and : #if value is set and :
# - not frozen # - not frozen
# - frozen and not force_default_on_freeze # - frozen and not force_default_on_freeze
@ -107,16 +107,16 @@ class Values(object):
pass pass
else: else:
value = self._getcallback_value(opt) value = self._getcallback_value(opt)
if opt.is_multi(): if opt.objimpl_is_multi():
value = Multi(value, self.context, opt) value = Multi(value, self.context, opt)
#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 = opt.getdefault() value = opt.objimpl_getdefault()
if opt.is_multi(): if opt.objimpl_is_multi():
value = Multi(value, self.context, opt) value = Multi(value, self.context, opt)
if validate and not opt.validate(value, self.context, 'validator' in setting): if validate and not opt.objimpl_validate(value, self.context, 'validator' in setting):
raise ValueError(_('invalid calculated value returned' raise ValueError(_('invalid calculated value returned'
' for option {0}: {1}').format(opt._name, value)) ' for option {0}: {1}').format(opt._name, value))
if self.is_default_owner(opt) and \ if self.is_default_owner(opt) and \
@ -135,11 +135,11 @@ class Values(object):
def _setitem(self, opt, value, force_permissive=False, force_properties=None): def _setitem(self, opt, value, force_permissive=False, force_properties=None):
#valid opt #valid opt
if not opt.validate(value, self.context, if not opt.objimpl_validate(value, self.context,
'validator' in self.context.cfgimpl_get_settings()): 'validator' in self.context.cfgimpl_get_settings()):
raise ValueError(_('invalid value {}' raise ValueError(_('invalid value {}'
' for option {}').format(value, opt._name)) ' for option {}').format(value, opt._name))
if opt.is_multi() and not isinstance(value, Multi): if opt.objimpl_is_multi() and not isinstance(value, Multi):
value = Multi(value, self.context, opt) value = Multi(value, self.context, opt)
self._setvalue(opt, value, force_permissive=force_permissive, self._setvalue(opt, value, force_permissive=force_permissive,
force_properties=force_properties) force_properties=force_properties)
@ -208,16 +208,16 @@ 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.get_multitype() == multitypes.slave: if self.opt.objimpl_get_multitype() == multitypes.slave:
value = self._valid_slave(value) value = self._valid_slave(value)
elif self.opt.get_multitype() == multitypes.master: elif self.opt.objimpl_get_multitype() == multitypes.master:
self._valid_master(value) self._valid_master(value)
super(Multi, self).__init__(value) super(Multi, self).__init__(value)
def _valid_slave(self, value): def _valid_slave(self, value):
#if slave, had values until master's one #if slave, had values until master's one
masterp = self.context.cfgimpl_get_description().get_path_by_opt( masterp = self.context.cfgimpl_get_description().objimpl_get_path_by_opt(
self.opt.get_master_slaves()) self.opt.objimpl_get_master_slaves())
mastervalue = getattr(self.context, masterp) mastervalue = getattr(self.context, masterp)
masterlen = len(mastervalue) masterlen = len(mastervalue)
if len(value) > masterlen or (len(value) < masterlen and if len(value) > masterlen or (len(value) < masterlen and
@ -227,7 +227,7 @@ class Multi(list):
self.opt._name, masterp)) self.opt._name, masterp))
elif len(value) < masterlen: elif len(value) < masterlen:
for num in range(0, masterlen - len(value)): for num in range(0, masterlen - len(value)):
value.append(self.opt.getdefault_multi()) value.append(self.opt.objimpl_getdefault_multi())
#else: same len so do nothing #else: same len so do nothing
return value return value
@ -244,7 +244,7 @@ class Multi(list):
self.opt._name, slave._name)) self.opt._name, slave._name))
elif len(value_slave) < masterlen: elif len(value_slave) < masterlen:
for num in range(0, masterlen - len(value_slave)): for num in range(0, masterlen - len(value_slave)):
value_slave.append(slave.getdefault_multi(), force=True) value_slave.append(slave.objimpl_getdefault_multi(), force=True)
def __setitem__(self, key, value): def __setitem__(self, key, value):
self._validate(value) self._validate(value)
@ -257,14 +257,14 @@ class Multi(list):
only if the option is a master only if the option is a master
""" """
if not force: if not force:
if self.opt.get_multitype() == multitypes.slave: if self.opt.objimpl_get_multitype() == multitypes.slave:
raise SlaveError(_("cannot append a value on a multi option {0}" raise SlaveError(_("cannot append a value on a multi option {0}"
" which is a slave").format(self.opt._name)) " which is a slave").format(self.opt._name))
elif self.opt.get_multitype() == multitypes.master: elif self.opt.objimpl_get_multitype() == multitypes.master:
for slave in self.opt.get_master_slaves(): for slave in self.opt.objimpl_get_master_slaves():
values = self.context.cfgimpl_get_values() values = self.context.cfgimpl_get_values()
if not values.is_default_owner(slave): if not values.is_default_owner(slave):
values[slave].append(slave.getdefault_multi(), values[slave].append(slave.objimpl_getdefault_multi(),
force=True) force=True)
self._validate(value) self._validate(value)
#assume not checking mandatory property #assume not checking mandatory property
@ -285,11 +285,11 @@ class Multi(list):
:return: the requested element :return: the requested element
""" """
if not force: if not force:
if self.opt.get_multitype() == multitypes.slave: if self.opt.objimpl_get_multitype() == multitypes.slave:
raise SlaveError(_("cannot pop a value on a multi option {0}" raise SlaveError(_("cannot pop a value on a multi option {0}"
" which is a slave").format(self.opt._name)) " which is a slave").format(self.opt._name))
elif self.opt.get_multitype() == multitypes.master: elif self.opt.objimpl_get_multitype() == multitypes.master:
for slave in self.opt.get_master_slaves(): for slave in self.opt.objimpl_get_master_slaves():
self.context.cfgimpl_get_values()[slave].pop(key, force=True) self.context.cfgimpl_get_values()[slave].pop(key, force=True)
self.context.cfgimpl_get_values()._setvalue(self.opt, self) self.context.cfgimpl_get_values()._setvalue(self.opt, self)
return super(Multi, self).pop(key) return super(Multi, self).pop(key)