From 682d9fe20774533ab26647d876ee1a2d4a3af953 Mon Sep 17 00:00:00 2001 From: Emmanuel Garette Date: Sat, 20 Apr 2013 21:58:52 +0200 Subject: [PATCH] add option name's validation and rename Option method with objimpl_ --- test/test_config.py | 38 +++--- test/test_config_api.py | 128 ++++-------------- test/test_option_default.py | 68 +++------- test/test_option_setting.py | 154 +++++++++++----------- test/test_option_with_special_name.py | 12 +- test/test_parsing_group.py | 40 +++--- tiramisu/config.py | 108 ++++------------ tiramisu/error.py | 5 - tiramisu/option.py | 180 ++++++++++++++------------ tiramisu/setting.py | 28 ++-- tiramisu/value.py | 54 ++++---- 11 files changed, 326 insertions(+), 489 deletions(-) diff --git a/test/test_config.py b/test/test_config.py index d487cb9..819c606 100644 --- a/test/test_config.py +++ b/test/test_config.py @@ -2,14 +2,16 @@ import autopath from py.test import raises -from tiramisu.config import * -from tiramisu.option import * +from tiramisu.config import Config +from tiramisu.option import IntOption, FloatOption, StrOption, ChoiceOption, \ + BoolOption, OptionDescription + def make_description(): gcoption = ChoiceOption('name', 'GC name', ('ref', 'framework'), 'ref') gcdummy = BoolOption('dummy', 'dummy', default=False) objspaceoption = ChoiceOption('objspace', 'Object space', - ('std', 'thunk'), 'std') + ('std', 'thunk'), 'std') booloption = BoolOption('bool', 'Test boolean option', default=True) intoption = IntOption('int', 'Test int option', default=0) floatoption = FloatOption('float', 'Test float option', default=2.3) @@ -21,25 +23,28 @@ def make_description(): gcgroup = OptionDescription('gc', '', [gcoption, gcdummy, floatoption]) descr = OptionDescription('tiram', '', [gcgroup, booloption, objspaceoption, - wantref_option, stroption, - wantframework_option, - intoption, boolop]) + wantref_option, stroption, + wantframework_option, + intoption, boolop]) return descr + def test_base_config(): gcdummy = BoolOption('dummy', 'dummy', default=False) descr = OptionDescription('tiramisu', '', [gcdummy]) cfg = Config(descr) - assert cfg.dummy == False + assert cfg.dummy is False dm = cfg.unwrap_from_path('dummy') assert dm._name == 'dummy' + def test_reset_value(): descr = make_description() cfg = Config(descr) - assert cfg.gc.dummy == False + assert cfg.gc.dummy is False cfg.gc.dummy = True - assert cfg.gc.dummy == True + assert cfg.gc.dummy is True + def test_base_config_and_groups(): descr = make_description() @@ -47,7 +52,7 @@ def test_base_config_and_groups(): config = Config(descr) config.bool = False assert config.gc.name == 'ref' - assert config.bool == False + assert config.bool is False nm = config.unwrap_from_path('gc.name') assert nm._name == 'name' gc = config.unwrap_from_path('gc') @@ -55,6 +60,7 @@ def test_base_config_and_groups(): #nm = config.unwrap_from_name('name') #assert nm._name == 'name' + def test_base_config_in_a_tree(): "how options are organized into a tree" descr = make_description() @@ -89,13 +95,6 @@ def test_base_config_in_a_tree(): assert config.gc.name == 'ref' 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(): descr = make_description() @@ -103,6 +102,5 @@ def test_cfgimpl_get_home_by_path(): config.bool = False assert config.cfgimpl_get_home_by_path('gc.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=True) == ['gc', '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'] diff --git a/test/test_config_api.py b/test/test_config_api.py index 492c7f8..599776d 100644 --- a/test/test_config_api.py +++ b/test/test_config_api.py @@ -2,14 +2,16 @@ import autopath from py.test import raises -from tiramisu.config import * -from tiramisu.option import * +from tiramisu.config import Config +from tiramisu.option import IntOption, FloatOption, StrOption, ChoiceOption, \ + BoolOption, OptionDescription + def make_description(): gcoption = ChoiceOption('name', 'GC name', ('ref', 'framework'), 'ref') gcdummy = BoolOption('dummy', 'dummy', default=False) objspaceoption = ChoiceOption('objspace', 'Object space', - ('std', 'thunk'), 'std') + ('std', 'thunk'), 'std') booloption = BoolOption('bool', 'Test boolean option', default=True) intoption = IntOption('int', 'Test int option', default=0) floatoption = FloatOption('float', 'Test float option', default=2.3) @@ -20,9 +22,9 @@ def make_description(): gcgroup = OptionDescription('gc', '', [gcoption, gcdummy, floatoption]) descr = OptionDescription('tiramisu', '', [gcgroup, booloption, objspaceoption, - wantref_option, stroption, - wantframework_option, - intoption, boolop]) + wantref_option, stroption, + wantframework_option, + intoption, boolop]) return descr @@ -34,86 +36,47 @@ def test_compare_configs(): conf2.wantref = True assert conf1 != conf2 assert hash(conf1) != hash(conf2) - assert conf1.getkey() != conf2.getkey() + #assert conf1.getkey() != conf2.getkey() conf1.wantref = True assert conf1 == 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(): "iteration on config object" s = StrOption("string", "", default="string") s2 = StrOption("string2", "", default="string2") - descr = OptionDescription("options", "", [s,s2]) + descr = OptionDescription("options", "", [s, s2]) config = Config(descr) assert [(name, value) for name, value in config] == \ - [('string', 'string'), ('string2', 'string2')] + [('string', 'string'), ('string2', 'string2')] + def test_iter_subconfig(): "iteration on config sub object" descr = make_description() conf = Config(descr) for (name, value), (gname, gvalue) in \ - zip(conf.gc, [("name", "ref"), ("dummy", False)]): + zip(conf.gc, [("name", "ref"), ("dummy", False)]): assert name == gname 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(): descr = make_description() 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(): "serialization of the whole config to a dict" @@ -131,19 +94,6 @@ def test_make_dict(): d2 = config.make_dict(flatten=True) 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(): "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(byvalue=False, byname='dummy', byattrs=dict(default=False)) == conf.unwrap_from_path('gc.dummy') + def test_does_not_find_in_config(): descr = make_description() conf = Config(descr) 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 -# diff --git a/test/test_option_default.py b/test/test_option_default.py index 833f4f1..3f7c32d 100644 --- a/test/test_option_default.py +++ b/test/test_option_default.py @@ -1,34 +1,35 @@ "test all types of option default values for options, add new option in a descr" import autopath -from py.test import raises -from tiramisu.config import * -from tiramisu.option import * -from tiramisu.error import PropertiesOptionError +from tiramisu.config import Config +from tiramisu.option import IntOption, FloatOption, StrOption, ChoiceOption, \ + BoolOption, OptionDescription + def make_description(): gcoption = ChoiceOption('name', 'GC name', ['ref', 'framework'], 'ref') gcdummy = BoolOption('dummy', 'dummy', default=False) objspaceoption = ChoiceOption('objspace', 'Object space', - ['std', 'thunk'], 'std') + ['std', 'thunk'], 'std') booloption = BoolOption('bool', 'Test boolean option', default=True) intoption = IntOption('int', 'Test int option', default=0) floatoption = FloatOption('float', 'Test float option', default=2.3) 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, - requires=['boolop']) + requires=['boolop']) wantframework_option = BoolOption('wantframework', 'Test requires', default=False, requires=['boolop']) gcgroup = OptionDescription('gc', '', [gcoption, gcdummy, floatoption]) descr = OptionDescription('tiramisu', '', [gcgroup, booloption, objspaceoption, - wantref_option, stroption, - wantframework_option, - intoption, boolop]) + wantref_option, stroption, + wantframework_option, + intoption, boolop]) return descr + #____________________________________________________________ # default values def test_default_is_none(): @@ -42,13 +43,15 @@ def test_default_is_none(): group = OptionDescription('group', '', [dummy1, dummy2]) config = Config(group) # so when the default value is not set, there is actually a default value - assert config.dummy1 == None - assert config.dummy2 == None + assert config.dummy1 is None + assert config.dummy2 is None + def test_set_defaut_value_from_option_object(): """Options have an available default setting and can give it back""" b = BoolOption("boolean", "", default=False) - assert b.getdefault() == False + assert b.objimpl_getdefault() is False + def test_force_default_on_freeze(): "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[dummy1].append('frozen') setting[dummy2].append('frozen') - assert config.dummy1 == False - assert config.dummy2 == False + assert config.dummy1 is 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(): "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)]) config = Config(descr) config.b = True -# config.override({'b': False}) -# assert config.b == False -#____________________________________________________________ -# test various option types + + def test_choice_with_no_default(): descr = OptionDescription("test", "", [ ChoiceOption("backend", "", ("c", "cli"))]) @@ -94,26 +83,9 @@ def test_choice_with_no_default(): assert config.backend is None config.backend = "c" + def test_choice_with_default(): descr = OptionDescription("test", "", [ ChoiceOption("backend", "", ("c", "cli"), default="cli")]) config = Config(descr) 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] diff --git a/test/test_option_setting.py b/test/test_option_setting.py index f3b9863..9ee9b02 100644 --- a/test/test_option_setting.py +++ b/test/test_option_setting.py @@ -5,8 +5,8 @@ from py.test import raises from tiramisu.setting import owners from tiramisu.config import Config from tiramisu.option import ChoiceOption, BoolOption, IntOption, FloatOption, \ - StrOption, OptionDescription, SymLinkOption -from tiramisu.error import ConflictOptionError, PropertiesOptionError + StrOption, OptionDescription +from tiramisu.error import PropertiesOptionError def make_description(): @@ -251,7 +251,7 @@ def test_multi_with_bool(): s = BoolOption("bool", "", default=[False], multi=True) descr = OptionDescription("options", "", [s]) config = Config(descr) - assert descr.bool.is_multi() is True + assert descr.bool.objimpl_is_multi() is True config.bool = [True, False] assert config.cfgimpl_get_values()[s] == [True, False] assert config.bool == [True, False] @@ -261,7 +261,7 @@ def test_multi_with_bool_two(): s = BoolOption("bool", "", default=[False], multi=True) descr = OptionDescription("options", "", [s]) config = Config(descr) - assert descr.bool.is_multi() is True + assert descr.bool.objimpl_is_multi() is True raises(ValueError, "config.bool = True") @@ -283,80 +283,80 @@ def test_choice_access_with_multi(): #____________________________________________________________ -def test_dwim_set(): - descr = OptionDescription("opt", "", [ - OptionDescription("sub", "", [ - BoolOption("b1", ""), - ChoiceOption("c1", "", ('a', 'b', 'c'), 'a'), - BoolOption("d1", ""), - ]), - BoolOption("b2", ""), - BoolOption("d1", ""), - ]) - c = Config(descr) - c.set(b1=False, c1='b') - assert not c.sub.b1 - assert c.sub.c1 == 'b' - # new config, because you cannot change values once they are set - c = Config(descr) - c.set(b2=False, **{'sub.c1': 'c'}) - assert not c.b2 - assert c.sub.c1 == 'c' - raises(ConflictOptionError, "c.set(d1=True)") - raises(AttributeError, "c.set(unknown='foo')") +#def test_dwim_set(): +# descr = OptionDescription("opt", "", [ +# OptionDescription("sub", "", [ +# BoolOption("b1", ""), +# ChoiceOption("c1", "", ('a', 'b', 'c'), 'a'), +# BoolOption("d1", ""), +# ]), +# BoolOption("b2", ""), +# BoolOption("d1", ""), +# ]) +# c = Config(descr) +# c.set(b1=False, c1='b') +# assert not c.sub.b1 +# assert c.sub.c1 == 'b' +# # new config, because you cannot change values once they are set +# c = Config(descr) +# c.set(b2=False, **{'sub.c1': 'c'}) +# assert not c.b2 +# assert c.sub.c1 == 'c' +# raises(ConflictOptionError, "c.set(d1=True)") +# raises(AttributeError, "c.set(unknown='foo')") -def test_more_set(): - descr = OptionDescription("opt", "", [ - OptionDescription("s1", "", [ - BoolOption("a", "", default=False)]), - IntOption("int", "", default=42)]) - d = {'s1.a': True, 'int': 23} - config = Config(descr) - config.set(**d) - assert config.s1.a - assert config.int == 23 +#def test_more_set(): +# descr = OptionDescription("opt", "", [ +# OptionDescription("s1", "", [ +# BoolOption("a", "", default=False)]), +# IntOption("int", "", default=42)]) +# d = {'s1.a': True, 'int': 23} +# config = Config(descr) +# config.set(**d) +# assert config.s1.a +# assert config.int == 23 -def test_set_with_hidden_option(): - boolopt = BoolOption("a", "", default=False, properties=(('hidden'),)) - descr = OptionDescription("opt", "", [ - OptionDescription("s1", "", [boolopt]), - IntOption("int", "", default=42)]) - d = {'s1.a': True, 'int': 23} - config = Config(descr) - setting = config.cfgimpl_get_settings() - setting.read_write() - raises(PropertiesOptionError, "config.set(**d)") - - -def test_set_with_unknown_option(): - boolopt = BoolOption("b", "", default=False) - descr = OptionDescription("opt", "", [ - OptionDescription("s1", "", [boolopt]), - IntOption("int", "", default=42)]) - d = {'s1.a': True, 'int': 23} - config = Config(descr) - raises(AttributeError, "config.set(**d)") - - -def test_set_symlink_option(): - boolopt = BoolOption("b", "", default=False) - linkopt = SymLinkOption("c", "s1.b", opt=boolopt) - descr = OptionDescription("opt", "", - [linkopt, OptionDescription("s1", "", [boolopt])]) - config = Config(descr) - setattr(config, "s1.b", True) - setattr(config, "s1.b", False) - assert config.s1.b is False - assert config.c is False - config.c = True - assert config.s1.b is True - assert config.c is True - config.c = False - assert config.s1.b is False - assert config.c is False - +#def test_set_with_hidden_option(): +# boolopt = BoolOption("a", "", default=False, properties=(('hidden'),)) +# descr = OptionDescription("opt", "", [ +# OptionDescription("s1", "", [boolopt]), +# IntOption("int", "", default=42)]) +# d = {'s1.a': True, 'int': 23} +# config = Config(descr) +# setting = config.cfgimpl_get_settings() +# setting.read_write() +# raises(PropertiesOptionError, "config.set(**d)") +# +# +#def test_set_with_unknown_option(): +# boolopt = BoolOption("b", "", default=False) +# descr = OptionDescription("opt", "", [ +# OptionDescription("s1", "", [boolopt]), +# IntOption("int", "", default=42)]) +# d = {'s1.a': True, 'int': 23} +# config = Config(descr) +# raises(AttributeError, "config.set(**d)") +# +# +#def test_set_symlink_option(): +# boolopt = BoolOption("b", "", default=False) +# linkopt = SymLinkOption("c", "s1.b", opt=boolopt) +# descr = OptionDescription("opt", "", +# [linkopt, OptionDescription("s1", "", [boolopt])]) +# config = Config(descr) +# setattr(config, "s1.b", True) +# setattr(config, "s1.b", False) +# assert config.s1.b is False +# assert config.c is False +# config.c = True +# assert config.s1.b is True +# assert config.c is True +# config.c = False +# assert config.s1.b is False +# assert config.c is False +# ##____________________________________________________________ #def test_config_impl_values(): # descr = make_description() @@ -401,8 +401,10 @@ def test_allow_multiple_changes_from_config(): config = Config(descr) config.string = "oh" assert config.string == "oh" - config.set(string2='blah') - assert config.bip.string2 == 'blah' + config.string = "blah" + assert config.string == "blah" +# config.set(string2='blah') +# assert config.bip.string2 == 'blah' # ____________________________________________________________ diff --git a/test/test_option_with_special_name.py b/test/test_option_with_special_name.py index 4e21a40..d425c0e 100644 --- a/test/test_option_with_special_name.py +++ b/test/test_option_with_special_name.py @@ -48,8 +48,10 @@ def test_optname_shall_not_start_with_numbers(): def test_option_has_an_api_name(): - print "FIXME" - #gcdummy = BoolOption('cfgimpl_get_settings', 'dummy', default=False) - #boolop = BoolOption('boolop', 'Test boolean option op', default=True) - #descr = OptionDescription('tiramisu', '', [gcdummy, boolop]) - #raises(ValueError, "cfg = Config(descr)") + raises(ValueError, "BoolOption('cfgimpl_get_settings', 'dummy', default=False)") + raises(ValueError, "BoolOption('unwrap_from_path', 'dummy', default=False)") + raises(ValueError, "BoolOption('objimpl_getdoc', 'dummy', default=False)") + raises(ValueError, "BoolOption('_unvalid', 'dummy', default=False)") + raises(ValueError, "BoolOption('6unvalid', 'dummy', default=False)") + BoolOption('unvalid6', 'dummy', default=False) + BoolOption('unvalid_', 'dummy', default=False) diff --git a/test/test_parsing_group.py b/test/test_parsing_group.py index f060a97..34019f7 100644 --- a/test/test_parsing_group.py +++ b/test/test_parsing_group.py @@ -27,13 +27,13 @@ def make_description(): master = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0]) interface1 = OptionDescription('interface1', '', [master]) - interface1.set_group_type(groups.family) + interface1.objimpl_set_group_type(groups.family) general = OptionDescription('general', '', [numero_etab, nom_machine, nombre_interfaces, activer_proxy_client, mode_conteneur_actif, adresse_serveur_ntp, time_zone]) - general.set_group_type(groups.family) + general.objimpl_set_group_type(groups.family) creole = OptionDescription('creole', 'first tiramisu configuration', [general, interface1]) descr = OptionDescription('baseconfig', 'baseconifgdescr', [creole]) return descr @@ -62,10 +62,10 @@ def test_get_group_type(): descr = make_description() config = Config(descr) grp = config.unwrap_from_path('creole.general') - assert grp.get_group_type() == groups.family - assert grp.get_group_type() == 'family' - assert isinstance(grp.get_group_type(), groups.GroupType) - raises(TypeError, 'grp.set_group_type(groups.default)') + assert grp.objimpl_get_group_type() == groups.family + assert grp.objimpl_get_group_type() == 'family' + assert isinstance(grp.objimpl_get_group_type(), groups.GroupType) + raises(TypeError, 'grp.objimpl_set_group_type(groups.default)') 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) 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.set_group_type(groups.master) - assert interface1.get_group_type() == groups.master + interface1.objimpl_set_group_type(groups.master) + assert interface1.objimpl_get_group_type() == groups.master def test_groups_with_master_in_config(): 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.set_group_type(groups.master) + interface1.objimpl_set_group_type(groups.master) Config(interface1) - assert interface1.get_group_type() == groups.master + assert interface1.objimpl_get_group_type() == groups.master 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]) - raises(ValueError, "interface1.set_group_type('toto')") + raises(ValueError, "interface1.objimpl_set_group_type('toto')") 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]) - 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(): @@ -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) subgroup = OptionDescription("subgroup", '', []) 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(): 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]) - 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) 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.set_group_type(groups.master) + interface1.objimpl_set_group_type(groups.master) maconfig = OptionDescription('toto', '', [interface1]) cfg = Config(maconfig) opt = cfg.unwrap_from_path("ip_admin_eth0.ip_admin_eth0") opt_slave = cfg.unwrap_from_path("ip_admin_eth0.netmask_admin_eth0") 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_slave) == owners.default 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) 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.set_group_type(groups.master) + interface1.objimpl_set_group_type(groups.master) maconfig = OptionDescription('toto', '', [interface1]) cfg = Config(maconfig) opt = cfg.unwrap_from_path("ip_admin_eth0.ip_admin_eth0") opt_slave = cfg.unwrap_from_path("ip_admin_eth0.netmask_admin_eth0") 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_slave) == owners.default 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) 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.set_group_type(groups.master) + interface1.objimpl_set_group_type(groups.master) maconfig = OptionDescription('toto', '', [interface1]) cfg = Config(maconfig) 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) 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.set_group_type(groups.master) + interface1.objimpl_set_group_type(groups.master) maconfig = OptionDescription('toto', '', [interface1]) cfg = Config(maconfig) cfg.ip_admin_eth0.ip_admin_eth0.append("192.168.230.145") diff --git a/tiramisu/config.py b/tiramisu/config.py index 3402a0e..a89f8e6 100644 --- a/tiramisu/config.py +++ b/tiramisu/config.py @@ -21,7 +21,7 @@ # the whole pypy projet is under MIT licence # ____________________________________________________________ #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.setting import groups, Setting from tiramisu.value import Values @@ -84,7 +84,7 @@ class SubConfig(object): self.cfgimpl_get_values().setitem(child, value, force_permissive=force_permissive) else: - child.setoption(self.cfgimpl_get_context(), value) + child._setoption(self.cfgimpl_get_context(), value) def __delattr__(self, name): child = getattr(self._cfgimpl_descr, name) @@ -114,11 +114,11 @@ class SubConfig(object): if name.startswith('_cfgimpl_') or name.startswith('cfgimpl_'): # if it were in __dict__ it would have been found already object.__getattr__(self, name) - opt_or_descr = getattr(self._cfgimpl_descr, name) + opt_or_descr = getattr(self.cfgimpl_get_description(), name) # symlink options if isinstance(opt_or_descr, SymLinkOption): 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, force_properties=force_properties, force_permissive=force_permissive) @@ -127,12 +127,6 @@ class SubConfig(object): True, False, force_permissive=force_permissive, 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) else: return self.cfgimpl_get_values().getitem(opt_or_descr, @@ -149,27 +143,27 @@ class SubConfig(object): force_properties=force_properties) return self, path[-1] - def getkey(self): - return self._cfgimpl_descr.getkey(self) - def __hash__(self): - return hash(self.getkey()) + return hash(self.cfgimpl_get_description().objimpl_getkey(self)) def __eq__(self, other): "Config comparison" if not isinstance(other, Config): 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): "Config comparison" + if not isinstance(other, Config): + return False return not self == other # ______________________________________________________________________ def __iter__(self): """Pythonesque way of parsing group's ordered options. 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): try: yield child._name, getattr(self, child._name) @@ -181,7 +175,7 @@ class SubConfig(object): def iter_all(self): """A way of parsing options **and** groups. iteration on Options and OptionDescriptions.""" - for child in self._cfgimpl_descr._children[1]: + for child in self.cfgimpl_get_description().objimpl_getchildren(): try: yield child._name, getattr(self, child._name) except GeneratorExit: @@ -202,13 +196,11 @@ class SubConfig(object): if group_type is not None: if not isinstance(group_type, groups.GroupType): 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): try: - if group_type is not None: - if child.get_group_type() == group_type: - yield child._name, getattr(self, child._name) - else: + if group_type is None or (group_type is not None and + child.objimpl_get_group_type() == group_type): yield child._name, getattr(self, child._name) except GeneratorExit: raise StopIteration @@ -230,31 +222,10 @@ class SubConfig(object): __repr__ = __str__ - def getpaths(self, include_groups=False, allpaths=False): - """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): + def cfgimpl_get_path(self): descr = self.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'): """ @@ -268,7 +239,7 @@ class SubConfig(object): return self.cfgimpl_get_context()._find(bytype, byname, byvalue, first=False, type_=type_, - _subpath=self.getpath()) + _subpath=self.cfgimpl_get_path()) 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, first=True, type_=type_, - _subpath=self.getpath()) + _subpath=self.cfgimpl_get_path()) def make_dict(self, flatten=False, _currpath=None, withoption=None, withvalue=None): """export the whole config into a `dict` @@ -293,7 +264,7 @@ class SubConfig(object): if withoption is None and withvalue is not None: raise ValueError(_("make_dict can't filtering with value without option")) if withoption is not None: - mypath = self.getpath() + mypath = self.cfgimpl_get_path() for path in self.cfgimpl_get_context()._find(bytype=Option, byname=withoption, byvalue=withvalue, @@ -301,7 +272,7 @@ class SubConfig(object): type_='path', _subpath=mypath): 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 == path: withoption = None @@ -316,7 +287,7 @@ class SubConfig(object): self._make_sub_dict(opt, path, pathsvalues, _currpath, flatten) #withoption can be set to None below ! if withoption is None: - for opt in self.cfgimpl_get_description().getchildren(): + for opt in self.cfgimpl_get_description().objimpl_getchildren(): path = opt._name self._make_sub_dict(opt, path, pathsvalues, _currpath, flatten) if _currpath == []: @@ -359,7 +330,7 @@ class Config(SubConfig): self._cfgimpl_build_all_paths() 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')): if 'values' in only: @@ -379,38 +350,7 @@ class Config(SubConfig): return getattr(homeconfig._cfgimpl_descr, path) return getattr(self._cfgimpl_descr, path) - def set(self, **kwargs): - """ - 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): + def cfgimpl_get_path(self): return None 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 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: config._getattr(path, force_properties=('mandatory',)) except PropertiesOptionError, err: diff --git a/tiramisu/error.py b/tiramisu/error.py index d6624f5..8780301 100644 --- a/tiramisu/error.py +++ b/tiramisu/error.py @@ -37,11 +37,6 @@ class PropertiesOptionError(AttributeError): super(PropertiesOptionError, self).__init__(msg) -class ConflictOptionError(StandardError): - "more than one option" - pass - - #____________config___________ class ConfigError(StandardError): """try to change owner for an option without value diff --git a/tiramisu/option.py b/tiramisu/option.py index d905de5..650953d 100644 --- a/tiramisu/option.py +++ b/tiramisu/option.py @@ -30,6 +30,8 @@ from tiramisu.setting import groups, multitypes from tiramisu.i18n import _ name_regexp = re.compile(r'^\d+') +forbidden_names = ['iter_all', 'iter_group', 'find', 'find_fisrt', + 'make_dict', 'unwrap_from_path'] def valid_name(name): @@ -37,7 +39,10 @@ def valid_name(name): name = str(name) except: 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 else: return False @@ -48,7 +53,7 @@ def valid_name(name): class BaseInformation(object): __slots__ = ('_informations') - def set_information(self, key, value): + def objimpl_set_information(self, key, value): """updates the information's attribute (wich is a dictionnary) @@ -57,7 +62,7 @@ class BaseInformation(object): """ self._informations[key] = value - def get_information(self, key, default=None): + def objimpl_get_information(self, key, default=None): """retrieves one information's item :param key: the item string (ex: "help") @@ -85,7 +90,6 @@ class Option(BaseInformation): requires=None, multi=False, callback=None, callback_params=None, validator=None, validator_args=None, properties=None): - #FIXME : validation de callback et callback_params !!! """ :param name: the option's name :param doc: the option's description @@ -107,7 +111,7 @@ class Option(BaseInformation): raise ValueError(_("invalid name: {0} for option").format(name)) self._name = name self._informations = {} - self.set_information('doc', doc) + self.objimpl_set_information('doc', doc) validate_requires_arg(requires, self._name) self._requires = requires self._multi = multi @@ -133,6 +137,11 @@ class Option(BaseInformation): raise ValueError(_("params defined for a callback function but " "no callback defined yet for option {0}").format(name)) 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) else: self._callback = None @@ -143,14 +152,14 @@ class Option(BaseInformation): # raise ValidateError("invalid default value {0} " # "for option {1} : not list type" # "".format(str(default), name)) - if not self.validate(default): + if not self.objimpl_validate(default): raise ValueError(_("invalid default value {0} " "for option {1}" "").format(str(default), name)) self._multitype = multitypes.default self._default_multi = default_multi 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} " "for option {1}").format(str(default), name)) self._default = default @@ -161,7 +170,7 @@ class Option(BaseInformation): ' must be a tuple').format(type(properties), self._name)) 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 validate: if true enables ``self._validator`` validation @@ -181,7 +190,7 @@ class Option(BaseInformation): if not self._validate(value): return False if cons is not None: - return cons.valid_consistency(self, value, context, None) + return cons._valid_consistency(self, value, context, None) else: if not isinstance(value, list): raise ValueError(_("invalid value {0} " @@ -197,52 +206,52 @@ class Option(BaseInformation): return False if not self._validate(val): 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 True - def getdefault(self, default_multi=False): + def objimpl_getdefault(self, default_multi=False): "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 else: return self.getdefault_multi() - def getdefault_multi(self): + def objimpl_getdefault_multi(self): "accessing the default value for a multi" return self._default_multi - def get_multitype(self): + def objimpl_get_multitype(self): return self._multitype - def get_master_slaves(self): + def objimpl_get_master_slaves(self): return self._master_slaves - def is_empty_by_default(self): + def objimpl_is_empty_by_default(self): "no default value has been set yet" - if ((not self.is_multi() and self._default is None) or - (self.is_multi() and (self._default == [] or None in self._default))): + if ((not self.objimpl_is_multi() and self._default is None) or + (self.objimpl_is_multi() and (self._default == [] or None in self._default))): return True return False - def getdoc(self): + def objimpl_getdoc(self): "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" if self._callback is None: return False else: return True - def getkey(self, value): + def objimpl_getkey(self, value): return value - def is_multi(self): + def objimpl_is_multi(self): return self._multi - def add_consistency(self, func, opts): + def objimpl_add_consistency(self, func, opts): pass if self._consistencies is None: self._consistencies = [] @@ -250,14 +259,14 @@ class Option(BaseInformation): opts = list(opts) opts.append(self) 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] descr = context.cfgimpl_get_description() for opt_ in opts: 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) if val is not None: if val in values: @@ -265,7 +274,7 @@ class Option(BaseInformation): values.append(val) return True - def cons_lower(self, value): + def _cons_lower(self, value): try: return value.islower() except AttributeError: @@ -274,8 +283,8 @@ class Option(BaseInformation): class ChoiceOption(Option): - __slots__ = ('_values', '_open_values', 'opt_type') - opt_type = 'string' + __slots__ = ('_values', '_open_values', '_opt_type') + _opt_type = 'string' def __init__(self, name, doc, values, default=None, default_multi=None, requires=None, multi=False, callback=None, @@ -306,40 +315,40 @@ class ChoiceOption(Option): class BoolOption(Option): - __slots__ = ('opt_type') - opt_type = 'bool' + __slots__ = ('_opt_type') + _opt_type = 'bool' def _validate(self, value): return isinstance(value, bool) class IntOption(Option): - __slots__ = ('opt_type') - opt_type = 'int' + __slots__ = ('_opt_type') + _opt_type = 'int' def _validate(self, value): return isinstance(value, int) class FloatOption(Option): - __slots__ = ('opt_type') - opt_type = 'float' + __slots__ = ('_opt_type') + _opt_type = 'float' def _validate(self, value): return isinstance(value, float) class StrOption(Option): - __slots__ = ('opt_type') - opt_type = 'string' + __slots__ = ('_opt_type') + _opt_type = 'string' def _validate(self, value): return isinstance(value, str) class UnicodeOption(Option): - __slots__ = ('opt_type') - opt_type = 'unicode' + __slots__ = ('_opt_type') + _opt_type = 'unicode' _empty = u'' def _validate(self, value): @@ -347,30 +356,30 @@ class UnicodeOption(Option): class SymLinkOption(object): - __slots__ = ('_name', 'opt', '_consistencies') - opt_type = 'symlink' + __slots__ = ('_name', '_opt', '_consistencies') + _opt_type = 'symlink' _consistencies = None def __init__(self, name, path, opt): self._name = name - self.opt = opt + self._opt = opt - def setoption(self, context, value): - path = context.cfgimpl_get_description().get_path_by_opt(self.opt) + def _setoption(self, context, value): + path = context.cfgimpl_get_description().objimpl_get_path_by_opt(self._opt) setattr(context, path, value) def __getattr__(self, name): - if name in ('_name', 'opt', 'setoption'): + if name in ('_name', '_opt', '_setoption', '_consistencies'): return object.__gettattr__(self, name) else: - return getattr(self.opt, name) + return getattr(self._opt, name) class IPOption(Option): - __slots__ = ('opt_type', '_only_private') - opt_type = 'ip' + __slots__ = ('_opt_type', '_only_private') + _opt_type = 'ip' - def set_private(self): + def objimpl_set_private(self): self._only_private = True def _validate(self, value): @@ -388,8 +397,8 @@ class IPOption(Option): class NetworkOption(Option): - __slots__ = ('opt_type') - opt_type = 'network' + __slots__ = ('_opt_type') + _opt_type = 'network' def _validate(self, value): try: @@ -400,8 +409,8 @@ class NetworkOption(Option): class NetmaskOption(Option): - __slots__ = ('opt_type') - opt_type = 'netmask' + __slots__ = ('_opt_type') + _opt_type = 'netmask' def __init__(self, name, doc, default=None, default_multi=None, requires=None, multi=False, callback=None, @@ -435,30 +444,30 @@ class NetmaskOption(Option): except ValueError: 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 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 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 descr = context.cfgimpl_get_description() if opt is opt_ipnetwork: 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) - if opt_netmask.is_multi(): + if opt_netmask.objimpl_is_multi(): val_netmask = val_netmask[index] if val_netmask is None: return True else: 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) - if opt_ipnetwork.is_multi(): + if opt_ipnetwork.objimpl_is_multi(): val_ipnetwork = val_ipnetwork[index] if val_ipnetwork is None: return True @@ -470,8 +479,8 @@ class NetmaskOption(Option): class DomainnameOption(Option): - __slots__ = ('opt_type', '_type', '_allow_ip') - opt_type = 'domainname' + __slots__ = ('_opt_type', '_type', '_allow_ip') + _opt_type = 'domainname' #allow_ip 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)) self._name = name self._informations = {} - self.set_information('doc', doc) + self.objimpl_set_information('doc', doc) child_names = [child._name for child in children] #better performance like this valid_child = copy(child_names) @@ -554,8 +563,8 @@ class OptionDescription(BaseInformation): # the group_type is useful for filtering OptionDescriptions in a config self._group_type = groups.default - def getdoc(self): - return self.get_information('doc') + def objimpl_getdoc(self): + return self.objimpl_get_information('doc') def __getattr__(self, name): try: @@ -564,33 +573,32 @@ class OptionDescription(BaseInformation): raise AttributeError(_('unknown Option {} in OptionDescription {}' '').format(name, self._name)) - def getkey(self, config): - return tuple([child.getkey(getattr(config, child._name)) - for child in self._children[1]]) + def objimpl_getkey(self, config): + return tuple([child.objimpl_getkey(getattr(config, child._name)) + 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 _currpath should not be provided (helps with recursion) """ - #FIXME : cache if _currpath is None: _currpath = [] paths = [] - for option in self._children[1]: + for option in self.objimpl_getchildren(): attr = option._name if isinstance(option, OptionDescription): if include_groups: paths.append('.'.join(_currpath + [attr])) - paths += option.getpaths(include_groups=include_groups, - _currpath=_currpath + [attr]) + paths += option.objimpl_getpaths(include_groups=include_groups, + _currpath=_currpath + [attr]) else: paths.append('.'.join(_currpath + [attr])) return paths - def getchildren(self): + def objimpl_getchildren(self): 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: return if _currpath is None: @@ -602,7 +610,7 @@ class OptionDescription(BaseInformation): if cache_path is None: cache_path = [self._name] cache_option = [self] - for option in self._children[1]: + for option in self.objimpl_getchildren(): attr = option._name if attr.startswith('_cfgimpl'): continue @@ -616,7 +624,7 @@ class OptionDescription(BaseInformation): _consistencies.setdefault(opt, []).append((func, opts)) else: _currpath.append(attr) - option.build_cache(cache_path, cache_option, _currpath, _consistencies) + option.objimpl_build_cache(cache_path, cache_option, _currpath, _consistencies) _currpath.pop() if save: #valid no duplicated option @@ -631,20 +639,20 @@ class OptionDescription(BaseInformation): self._cache_paths = (tuple(cache_option), tuple(cache_path)) self._consistencies = _consistencies - def get_opt_by_path(self, path): + def obgimpl_get_opt_by_path(self, path): try: return self._cache_paths[0][self._cache_paths[1].index(path)] except ValueError: raise AttributeError(_('no option for path {}').format(path)) - def get_path_by_opt(self, opt): + def objimpl_get_path_by_opt(self, opt): try: return self._cache_paths[1][self._cache_paths[0].index(opt)] except ValueError: 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 :param group_type: an instance of `GroupType` or `MasterGroupType` @@ -661,11 +669,11 @@ class OptionDescription(BaseInformation): #for collect all slaves slaves = [] master = None - for child in self._children[1]: + for child in self.objimpl_getchildren(): if isinstance(child, OptionDescription): raise ValueError(_("master group {} shall not have " "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}" ": this option is not a multi" "").format(child._name, self._name)) @@ -679,7 +687,7 @@ class OptionDescription(BaseInformation): raise ValueError(_('master group with wrong master name for {}' '').format(self._name)) master._master_slaves = tuple(slaves) - for child in self._children[1]: + for child in self.objimpl_getchildren(): if child != master: child._master_slaves = master child._multitype = multitypes.slave @@ -689,10 +697,10 @@ class OptionDescription(BaseInformation): else: 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 - def valid_consistency(self, opt, value, context, index): + def _valid_consistency(self, opt, value, context, index): consistencies = self._consistencies.get(opt) if consistencies is not None: for consistency in consistencies: diff --git a/tiramisu/setting.py b/tiramisu/setting.py index c3372ce..de698e9 100644 --- a/tiramisu/setting.py +++ b/tiramisu/setting.py @@ -26,6 +26,10 @@ from tiramisu.i18n import _ 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: @@ -303,25 +307,19 @@ class Setting(object): 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): "convenience method to freeze, hidde and disable" - self.append('everything_frozen') - self.append('frozen') # can be usefull... - self.remove('hidden') - self.append('disabled') - self.append('mandatory') - self.append('validator') - self.remove('permissive') + self._read(ro_remove, ro_append) def read_write(self): "convenience method to freeze, hidde and disable" - self.remove('everything_frozen') - self.append('frozen') # can be usefull... - self.append('hidden') - self.append('disabled') - self.remove('mandatory') - self.append('validator') - self.remove('permissive') + self._read(rw_remove, rw_append) def _set_cache(self, opt, props): if 'expire' in self: @@ -355,7 +353,7 @@ def apply_requires(opt, config): settings = config.cfgimpl_get_settings() setting = Property(settings, settings._get_properties(opt, False), opt) 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(): matches = False for require in requires: diff --git a/tiramisu/value.py b/tiramisu/value.py index 3bf42e6..a58dd3b 100644 --- a/tiramisu/value.py +++ b/tiramisu/value.py @@ -43,8 +43,8 @@ class Values(object): "return value or default value if not set" #if no value if opt not in self._values: - value = opt.getdefault() - if opt.is_multi(): + value = opt.objimpl_getdefault() + if opt.objimpl_is_multi(): value = Multi(value, self.context, opt) else: #if value @@ -62,11 +62,11 @@ class Values(object): def _is_empty(self, opt, value): "convenience method to know if an option is empty" empty = opt._empty - if (not opt.is_multi() and (value is None or value == empty)) or \ - (opt.is_multi() and (value == [] or - None in value or empty in value)): + if (not opt.objimpl_is_multi() and (value is None or value == empty)) or \ + (opt.objimpl_is_multi() and (value == [] or + None in value or empty in value)): 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 False @@ -97,7 +97,7 @@ class Values(object): setting = self.context.cfgimpl_get_settings() value = self._get_value(opt) is_frozen = 'frozen' in setting[opt] - if opt.has_callback(): + if opt.objimpl_has_callback(): #if value is set and : # - not frozen # - frozen and not force_default_on_freeze @@ -107,16 +107,16 @@ class Values(object): pass else: value = self._getcallback_value(opt) - if opt.is_multi(): + if opt.objimpl_is_multi(): value = Multi(value, self.context, opt) #suppress value if already set self._reset(opt) # frozen and force default elif is_frozen and 'force_default_on_freeze' in setting[opt]: - value = opt.getdefault() - if opt.is_multi(): + value = opt.objimpl_getdefault() + if opt.objimpl_is_multi(): 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' ' for option {0}: {1}').format(opt._name, value)) 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): #valid opt - if not opt.validate(value, self.context, - 'validator' in self.context.cfgimpl_get_settings()): + if not opt.objimpl_validate(value, self.context, + 'validator' in self.context.cfgimpl_get_settings()): raise ValueError(_('invalid value {}' ' 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) self._setvalue(opt, value, force_permissive=force_permissive, force_properties=force_properties) @@ -208,16 +208,16 @@ class Multi(list): self.context = context if not isinstance(value, list): value = [value] - if self.opt.get_multitype() == multitypes.slave: + if self.opt.objimpl_get_multitype() == multitypes.slave: value = self._valid_slave(value) - elif self.opt.get_multitype() == multitypes.master: + elif self.opt.objimpl_get_multitype() == multitypes.master: self._valid_master(value) super(Multi, self).__init__(value) def _valid_slave(self, value): #if slave, had values until master's one - masterp = self.context.cfgimpl_get_description().get_path_by_opt( - self.opt.get_master_slaves()) + masterp = self.context.cfgimpl_get_description().objimpl_get_path_by_opt( + self.opt.objimpl_get_master_slaves()) mastervalue = getattr(self.context, masterp) masterlen = len(mastervalue) if len(value) > masterlen or (len(value) < masterlen and @@ -227,7 +227,7 @@ class Multi(list): self.opt._name, masterp)) elif len(value) < masterlen: 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 return value @@ -244,7 +244,7 @@ class Multi(list): self.opt._name, slave._name)) elif len(value_slave) < masterlen: 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): self._validate(value) @@ -257,14 +257,14 @@ class Multi(list): only if the option is a master """ 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}" " which is a slave").format(self.opt._name)) - elif self.opt.get_multitype() == multitypes.master: - for slave in self.opt.get_master_slaves(): + elif self.opt.objimpl_get_multitype() == multitypes.master: + for slave in self.opt.objimpl_get_master_slaves(): values = self.context.cfgimpl_get_values() if not values.is_default_owner(slave): - values[slave].append(slave.getdefault_multi(), + values[slave].append(slave.objimpl_getdefault_multi(), force=True) self._validate(value) #assume not checking mandatory property @@ -285,11 +285,11 @@ class Multi(list): :return: the requested element """ 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}" " which is a slave").format(self.opt._name)) - elif self.opt.get_multitype() == multitypes.master: - for slave in self.opt.get_master_slaves(): + elif self.opt.objimpl_get_multitype() == multitypes.master: + for slave in self.opt.objimpl_get_master_slaves(): self.context.cfgimpl_get_values()[slave].pop(key, force=True) self.context.cfgimpl_get_values()._setvalue(self.opt, self) return super(Multi, self).pop(key)