diff --git a/test/new_api/test_option_setting.py b/test/new_api/test_option_setting.py index eb25abf..77f2d91 100644 --- a/test/new_api/test_option_setting.py +++ b/test/new_api/test_option_setting.py @@ -252,8 +252,8 @@ def test_multi_with_requires_that_is_masterslave(): b = IntOption('int', 'Test int option', default=[0], multi=True) c = StrOption('str', 'Test string option', requires=[{'option': b, 'expected': 1, 'action': 'hidden'}], multi=True) descr = MasterSlaves("int", "", [b, c]) - #descr.impl_set_group_type(groups.master) - Config(descr) + od = OptionDescription('root', '', [descr]) + Config(od) def test_multi_with_requires_that_is_masterslave_master(): diff --git a/test/new_api/test_parsing_group.py b/test/new_api/test_parsing_group.py new file mode 100644 index 0000000..66848f2 --- /dev/null +++ b/test/new_api/test_parsing_group.py @@ -0,0 +1,594 @@ +# coding: utf-8 +from .autopath import do_autopath +do_autopath() + +from tiramisu.setting import groups, owners +from tiramisu import ChoiceOption, BoolOption, IntOption, \ + StrOption, OptionDescription, MasterSlaves, Config, getapi +from tiramisu.error import SlaveError, PropertiesOptionError, APIError, ConfigError + +from py.test import raises + + +def make_description(): + numero_etab = StrOption('numero_etab', "identifiant de l'établissement") + nom_machine = StrOption('nom_machine', "nom de la machine", default="eoleng") + nombre_interfaces = IntOption('nombre_interfaces', "nombre d'interfaces à activer", + default=1) + activer_proxy_client = BoolOption('activer_proxy_client', "utiliser un proxy", + default=False) + mode_conteneur_actif = BoolOption('mode_conteneur_actif', "le serveur est en mode conteneur", + default=False) + mode_conteneur_actif2 = BoolOption('mode_conteneur_actif2', "le serveur est en mode conteneur2", + default=False, properties=('hidden',)) + + adresse_serveur_ntp = StrOption('serveur_ntp', "adresse serveur ntp", multi=True) + time_zone = ChoiceOption('time_zone', 'fuseau horaire du serveur', + ('Paris', 'Londres'), 'Paris') + + ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé") + netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau") + + master = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0]) + interface1 = OptionDescription('interface1', '', [master]) + interface1.impl_set_group_type(groups.family) + + general = OptionDescription('general', '', [numero_etab, nom_machine, + nombre_interfaces, activer_proxy_client, + mode_conteneur_actif, mode_conteneur_actif2, + adresse_serveur_ntp, time_zone]) + general.impl_set_group_type(groups.family) + new = OptionDescription('new', '', [], properties=('hidden',)) + new.impl_set_group_type(groups.family) + creole = OptionDescription('creole', 'first tiramisu configuration', [general, interface1, new]) + descr = OptionDescription('baseconfig', 'baseconifgdescr', [creole]) + return descr + + +def test_base_config(): + descr = make_description() + api = getapi(Config(descr)) + api.property.read_write() + assert api.option('creole.general.activer_proxy_client').value.get() is False + assert api.option('creole.general.nom_machine').value.get() == "eoleng" + assert api.option.find_first('nom_machine', type='value') == "eoleng" + result = {'general.numero_etab': None, 'general.nombre_interfaces': 1, + 'general.serveur_ntp': [], 'interface1.ip_admin_eth0.ip_admin_eth0': None, + 'general.mode_conteneur_actif': False, 'general.time_zone': 'Paris', + 'interface1.ip_admin_eth0.netmask_admin_eth0': None, 'general.nom_machine': + 'eoleng', 'general.activer_proxy_client': False} + assert api.option('creole').make_dict() == result + result = {'serveur_ntp': [], 'mode_conteneur_actif': False, + 'ip_admin_eth0': None, 'time_zone': 'Paris', 'numero_etab': None, + 'netmask_admin_eth0': None, 'nom_machine': 'eoleng', 'activer_proxy_client': + False, 'nombre_interfaces': 1} + assert api.option('creole').make_dict(flatten=True) == result + + +def test_make_dict_filter(): + descr = make_description() + api = getapi(Config(descr)) + api.property.read_write() + subresult = {'numero_etab': None, 'nombre_interfaces': 1, + 'serveur_ntp': [], 'mode_conteneur_actif': False, + 'time_zone': 'Paris', 'nom_machine': 'eoleng', + 'activer_proxy_client': False} + result = {} + for key, value in subresult.items(): + result['general.' + key] = value + assert api.option('creole').make_dict(withoption='numero_etab') == result + raises(AttributeError, "api.option('creole').make_dict(withoption='numero_etab', withvalue='toto')") + assert api.option('creole').make_dict(withoption='numero_etab', withvalue=None) == result + assert api.option('creole.general').make_dict(withoption='numero_etab') == subresult + + +def test_get_group_type(): + descr = make_description() + api = getapi(Config(descr)) + api.property.read_write() + grp = api.option('creole.general') + assert grp.group_type() == groups.family + assert grp.group_type() == 'family' + assert isinstance(grp.group_type(), groups.GroupType) + #raises(TypeError, 'grp.impl_set_group_type(groups.default)') + + +def test_iter_on_groups(): + descr = make_description() + api = getapi(Config(descr)) + api.property.read_write() + result = list(api.option('creole').list('optiondescription', group_type=groups.family)) + group_names = [res[0] for res in result] + assert group_names == ['general', 'interface1'] + for i in api.option('creole').list('optiondescription', group_type=groups.family): + #test StopIteration + break + + +def test_iter_on_groups_force_permissive(): + descr = make_description() + api = getapi(Config(descr)) + api.property.read_write() + api.permissive.set(frozenset(['hidden'])) + #result = list(config.creole.general.__iter__(force_permissive=True)) + group_names = list(api.forcepermissive.option('creole.general').list()) + ass = ['numero_etab', 'nom_machine', 'nombre_interfaces', + 'activer_proxy_client', 'mode_conteneur_actif', + 'mode_conteneur_actif2', 'serveur_ntp', 'time_zone'] + assert group_names == ass + group_names = list(api.option('creole.general').list()) + ass.remove('mode_conteneur_actif2') + assert group_names == ass + + +def test_iter_group_on_groups_force_permissive(): + descr = make_description() + api = getapi(Config(descr)) + api.property.read_write() + api.permissive.set(frozenset(['hidden'])) + result = list(api.forcepermissive.option('creole').list(type='optiondescription', group_type=groups.family)) + group_names = [res[0] for res in result] + assert group_names == ['general', 'interface1', 'new'] + + +def test_iter_on_groups_props(): + descr = make_description() + api = getapi(Config(descr)) + api.property.read_write() + api.option('creole.interface1').property.add('disabled') + result = list(api.option('creole').list(type='optiondescription', group_type=groups.family)) + group_names = [res[0] for res in result] + assert group_names == ['general'] + + +def test_iter_on_empty_group(): + api = getapi(Config(OptionDescription("name", "descr", []))) + api.property.read_write() + result = list(api.option.list(type='optiondescription')) + assert result == [] + + +def test_iter_not_group(): + api = getapi(Config(OptionDescription("name", "descr", []))) + api.property.read_write() + raises(TypeError, "list(api.option.list(type='optiondescription', group_type='family'))") + + +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 = MasterSlaves('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0]) + #interface1.impl_set_group_type(groups.master) + assert interface1.impl_get_group_type() == groups.master + + +def test_groups_with_master_in_root(): + 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 = MasterSlaves('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0]) + raises(ConfigError, "Config(interface1)") + + +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 = MasterSlaves('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0]) + od = OptionDescription('root', '', [interface1]) + Config(od) + assert interface1.impl_get_group_type() == groups.master + + +def test_groups_with_master_hidden_in_config(): + ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True, properties=('hidden',)) + netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True, properties=('hidden',)) + interface1 = MasterSlaves('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0]) + od = OptionDescription('root', '', [interface1]) + api = getapi(Config(od)) + api.property.read_write() + api.permissive.set(frozenset(['hidden'])) + assert api.forcepermissive.option('ip_admin_eth0.ip_admin_eth0').value.get() == [] + api.forcepermissive.option('ip_admin_eth0.ip_admin_eth0').value.set(['192.168.1.1']) + assert api.forcepermissive.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get() is None + raises(PropertiesOptionError, "api.option('ip_admin_eth0.ip_admin_eth0').value.get()") + raises(PropertiesOptionError, "api.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get()") + + +def test_groups_with_master_hidden_in_config2(): + 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, properties=('hidden',)) + interface1 = MasterSlaves('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0]) + od = OptionDescription('root', '', [interface1]) + api = getapi(Config(od)) + api.property.read_write() + api.permissive.set(frozenset(['hidden'])) + assert api.forcepermissive.option('ip_admin_eth0.ip_admin_eth0').value.get() == [] + assert api.option('ip_admin_eth0.ip_admin_eth0').value.get() == [] + api.forcepermissive.option('ip_admin_eth0.ip_admin_eth0').value.set(['192.168.1.1']) + raises(PropertiesOptionError, "api.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get()") + api.option('ip_admin_eth0.ip_admin_eth0').value.reset() + assert api.forcepermissive.option('ip_admin_eth0.ip_admin_eth0').value.get() == [] + #del + api.option('ip_admin_eth0.ip_admin_eth0').value.set(['192.168.1.1']) + api.property.pop('hidden') + assert api.forcepermissive.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get() is None + api.forcepermissive.option('ip_admin_eth0.netmask_admin_eth0', 0).value.set('255.255.255.0') + assert api.forcepermissive.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get() == '255.255.255.0' + api.property.add('hidden') + api.option('ip_admin_eth0.ip_admin_eth0').value.reset() + api.option('ip_admin_eth0.ip_admin_eth0').value.set(['192.168.1.1']) + api.property.pop('hidden') + assert api.forcepermissive.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get() is None + + +def test_groups_with_master_hidden_in_config3(): + #if master is hidden, slave are hidden too + ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True, properties=('hidden',)) + netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True) + interface1 = MasterSlaves('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0]) + od = OptionDescription('root', '', [interface1]) + #interface1.impl_set_group_type(groups.master) + api = getapi(Config(od)) + api.property.read_write() + api.permissive.set(frozenset(['hidden'])) + assert api.forcepermissive.option('ip_admin_eth0.ip_admin_eth0').value.get() == [] + api.forcepermissive.option('ip_admin_eth0.ip_admin_eth0').value.set(['192.168.1.1']) + assert api.forcepermissive.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get() is None + raises(PropertiesOptionError, "api.option('ip_admin_eth0.ip_admin_eth0').value.get()") + raises(PropertiesOptionError, "api.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get()") + + +def test_allowed_groups(): + ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True) + netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True) + interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0]) + interface1 + raises(ValueError, "interface1.impl_set_group_type('toto')") + + +def test_values_with_master_disabled_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 = MasterSlaves('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0]) + #interface1.impl_set_group_type(groups.master) + maconfig = OptionDescription('toto', '', [interface1]) + api = getapi(Config(maconfig)) + api.property.read_write() + api.option('ip_admin_eth0.ip_admin_eth0').value.set(['192.168.230.145']) + api.option('ip_admin_eth0.ip_admin_eth0').value.pop(0) + api.option('ip_admin_eth0.ip_admin_eth0').value.set(['192.168.230.145']) + api.option('ip_admin_eth0.netmask_admin_eth0', 0).value.set("192.168.230.145") + api.option('ip_admin_eth0.netmask_admin_eth0', 0).value.reset() + api.option('ip_admin_eth0.ip_admin_eth0').property.add('disabled') + raises(PropertiesOptionError, "api.option('ip_admin_eth0.netmask_admin_eth0', 0).value.set('192.168.230.145')") + + +def test_sub_group_in_master_group(): + 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) + subgroup = OptionDescription("subgroup", '', []) + raises(ValueError, "MasterSlaves('ip_admin_eth0', '', [subgroup, ip_admin_eth0, netmask_admin_eth0])") + + +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") + raises(ValueError, "MasterSlaves('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])") + + +#____________________________________________________________ +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 = MasterSlaves('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0]) + #interface1.impl_set_group_type(groups.master) + maconfig = OptionDescription('toto', '', [interface1]) + api = getapi(Config(maconfig)) + api.property.read_write() + owner = api.owner.get() + assert interface1.impl_get_group_type() == groups.master + assert api.option('ip_admin_eth0.ip_admin_eth0').owner.isdefault() + # + api.option('ip_admin_eth0.ip_admin_eth0').value.set(["192.168.230.145"]) + assert api.option('ip_admin_eth0.ip_admin_eth0').value.get() == ["192.168.230.145"] + assert api.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get() is None + assert api.option('ip_admin_eth0.ip_admin_eth0').owner.get() == owner + assert api.option('ip_admin_eth0.netmask_admin_eth0', 0).owner.isdefault() + api.option('ip_admin_eth0.ip_admin_eth0').value.set(["192.168.230.145", "192.168.230.147"]) + raises(APIError, "api.option('ip_admin_eth0.netmask_admin_eth0').value.set([None])") + raises(APIError, "api.option('ip_admin_eth0.netmask_admin_eth0').value.pop(0)") + + +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 = MasterSlaves('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0]) + #interface1.impl_set_group_type(groups.master) + maconfig = OptionDescription('toto', '', [interface1]) + api = getapi(Config(maconfig)) + api.property.read_write() + owner = api.owner.get() + assert interface1.impl_get_group_type() == groups.master + assert api.option('ip_admin_eth0.ip_admin_eth0').owner.isdefault() + api.option('ip_admin_eth0.ip_admin_eth0').value.set(["192.168.230.145"]) + assert api.option('ip_admin_eth0.ip_admin_eth0').owner.get() == owner + assert api.option('ip_admin_eth0.netmask_admin_eth0', 0).owner.isdefault() + api.option('ip_admin_eth0.ip_admin_eth0').value.reset() + assert api.option('ip_admin_eth0.ip_admin_eth0').owner.isdefault() + assert api.option('ip_admin_eth0.ip_admin_eth0').value.get() == [] + #reset + api.option('ip_admin_eth0.ip_admin_eth0').value.set(["192.168.230.145"]) + api.option('ip_admin_eth0.ip_admin_eth0').value.reset() + assert api.option('ip_admin_eth0.ip_admin_eth0').owner.isdefault() + assert api.option('ip_admin_eth0.ip_admin_eth0').value.get() == [] + + +def test_reset_values_with_master_and_slaves_default_value(): + ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True, default=['192.168.230.145']) + netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True, default=['255.255.255.0']) + raises(ValueError, "MasterSlaves('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])") + + +def test_reset_values_with_master_and_slaves_default(): + ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True, default=['192.168.230.145']) + netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True) + interface1 = MasterSlaves('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0]) + #interface1.impl_set_group_type(groups.master) + maconfig = OptionDescription('toto', '', [interface1]) + api = getapi(Config(maconfig)) + api.property.read_write() + owner = api.owner.get() + assert api.option('ip_admin_eth0.ip_admin_eth0').owner.isdefault() + assert api.option('ip_admin_eth0.netmask_admin_eth0', 0).owner.isdefault() + + api.option('ip_admin_eth0.ip_admin_eth0').value.set(['192.168.230.146']) + assert api.option('ip_admin_eth0.ip_admin_eth0').owner.get() == owner + assert api.option('ip_admin_eth0.netmask_admin_eth0', 0).owner.isdefault() + api.option('ip_admin_eth0.ip_admin_eth0').value.reset() + assert api.option('ip_admin_eth0.ip_admin_eth0').owner.isdefault() + assert api.option('ip_admin_eth0.netmask_admin_eth0', 0).owner.isdefault() + assert api.option('ip_admin_eth0.ip_admin_eth0').value.get() == ['192.168.230.145'] + api.option('ip_admin_eth0.netmask_admin_eth0', 0).value.set(None) + + api.option('ip_admin_eth0.ip_admin_eth0').value.set(['192.168.230.146']) + api.option('ip_admin_eth0.netmask_admin_eth0', 0).value.set('255.255.255.0') + assert api.option('ip_admin_eth0.ip_admin_eth0').owner.get() == owner + assert api.option('ip_admin_eth0.netmask_admin_eth0', 0).owner.get() == owner + api.option('ip_admin_eth0.ip_admin_eth0').value.reset() + assert api.option('ip_admin_eth0.ip_admin_eth0').owner.isdefault() + assert api.option('ip_admin_eth0.netmask_admin_eth0', 0).owner.get() == owners.default + assert api.option('ip_admin_eth0.ip_admin_eth0').value.get() == ['192.168.230.145'] + api.option('ip_admin_eth0.netmask_admin_eth0', 0).value.set(None) + + api.option('ip_admin_eth0.netmask_admin_eth0', 0).value.set('255.255.255.0') + assert api.option('ip_admin_eth0.ip_admin_eth0').owner.isdefault() + assert api.option('ip_admin_eth0.netmask_admin_eth0', 0).owner.get() == owner + api.option('ip_admin_eth0.ip_admin_eth0').value.reset() + assert api.option('ip_admin_eth0.ip_admin_eth0').owner.isdefault() + assert api.option('ip_admin_eth0.netmask_admin_eth0', 0).owner.isdefault() + assert api.option('ip_admin_eth0.ip_admin_eth0').value.get() == ['192.168.230.145'] + api.option('ip_admin_eth0.netmask_admin_eth0', 0).value.set(None) + + +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 = MasterSlaves('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0]) + #interface1.impl_set_group_type(groups.master) + maconfig = OptionDescription('toto', '', [interface1]) + api = getapi(Config(maconfig)) + api.property.read_write() + raises(SlaveError, + "api.option('ip_admin_eth0.netmask_admin_eth0', 0).value.set('255.255.255.0')") + api.option('ip_admin_eth0.ip_admin_eth0').value.set(['192.168.230.145']) + api.option('ip_admin_eth0.netmask_admin_eth0', 0).value.set('255.255.255.0') + api.option('ip_admin_eth0.netmask_admin_eth0', 0).value.reset() + api.option('ip_admin_eth0.netmask_admin_eth0', 0).value.set('255.255.255.0') + # + api.option('ip_admin_eth0.ip_admin_eth0').value.set(['192.168.230.145', '192.168.230.145']) + assert api.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get() == '255.255.255.0' + assert api.option('ip_admin_eth0.netmask_admin_eth0', 1).value.get() is None + api.option('ip_admin_eth0.netmask_admin_eth0', 0).value.set('255.255.255.0') + api.option('ip_admin_eth0.netmask_admin_eth0', 1).value.set('255.255.255.0') + raises(APIError, "api.option('ip_admin_eth0.netmask_admin_eth0', 1).value.pop(1)") + #reset + api.option('ip_admin_eth0.ip_admin_eth0').value.set(['192.168.230.145', + '192.168.230.145', + '192.168.230.145']) + api.option('ip_admin_eth0.ip_admin_eth0').value.reset() + assert api.option('ip_admin_eth0.ip_admin_eth0').value.get() == [] + + +def test_values_with_master_and_slaves_pop(): + 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 = MasterSlaves('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0]) + #interface1.impl_set_group_type(groups.master) + maconfig = OptionDescription('toto', '', [interface1]) + api = getapi(Config(maconfig)) + api.property.read_write() + api.option('ip_admin_eth0.ip_admin_eth0').value.set(['192.168.230.145']) + api.option('ip_admin_eth0.netmask_admin_eth0', 0).value.set('255.255.255.0') + api.option('ip_admin_eth0.ip_admin_eth0').value.set(['192.168.230.145', '192.168.230.146']) + api.option('ip_admin_eth0.netmask_admin_eth0', 1).value.set('255.255.0.0') + assert api.option('ip_admin_eth0.ip_admin_eth0').value.get() == ['192.168.230.145', '192.168.230.146'] + assert api.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get() == '255.255.255.0' + assert api.option('ip_admin_eth0.netmask_admin_eth0', 1).value.get() == '255.255.0.0' + api.option('ip_admin_eth0.ip_admin_eth0').value.pop(0) + assert api.option('ip_admin_eth0.ip_admin_eth0').value.get() == ['192.168.230.146'] + assert api.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get() == '255.255.0.0' + + +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 = MasterSlaves('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0]) + #interface1.impl_set_group_type(groups.master) + maconfig = OptionDescription('toto', '', [interface1]) + api = getapi(Config(maconfig)) + api.property.read_write() + api.option('ip_admin_eth0.ip_admin_eth0').value.set(["192.168.230.145"]) + api.option('ip_admin_eth0.ip_admin_eth0').value.set(["192.168.230.145"]) + api.option('ip_admin_eth0.ip_admin_eth0').value.set(["192.168.230.145", "192.168.230.145"]) + api.option('ip_admin_eth0.netmask_admin_eth0', 0).value.set('255.255.255.0') + api.option('ip_admin_eth0.netmask_admin_eth0', 1).value.set('255.255.255.0') + raises(SlaveError, "api.option('ip_admin_eth0.ip_admin_eth0').value.set(['192.168.230.145'])") + assert api.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get() == '255.255.255.0' + assert api.option('ip_admin_eth0.netmask_admin_eth0', 1).value.get() == '255.255.255.0' + api.option('ip_admin_eth0.ip_admin_eth0').value.pop(1) + assert api.option('ip_admin_eth0.ip_admin_eth0').value.get() == ["192.168.230.145"] + assert api.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get() == '255.255.255.0' + api.option('ip_admin_eth0.ip_admin_eth0').value.reset() + assert api.option('ip_admin_eth0.ip_admin_eth0').value.get() == [] + + +def test_values_with_master_and_slaves_master_pop(): + 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 = MasterSlaves('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0]) + maconfig = OptionDescription('toto', '', [interface1]) + api = getapi(Config(maconfig)) + api.property.read_write() + api.option('ip_admin_eth0.ip_admin_eth0').value.set(["192.168.230.145", "192.168.230.146"]) + api.option('ip_admin_eth0.netmask_admin_eth0', 1).value.set('255.255.0.0') + assert api.option('ip_admin_eth0.ip_admin_eth0').value.get() == ["192.168.230.145", "192.168.230.146"] + assert api.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get() == None + assert api.option('ip_admin_eth0.netmask_admin_eth0', 1).value.get() == '255.255.0.0' + assert api.value.get_modified() == {'ip_admin_eth0.ip_admin_eth0': ( + 'user', + ('192.168.230.145', '192.168.230.146')), + 'ip_admin_eth0.netmask_admin_eth0': ( + {'1': 'user'}, + {'1': '255.255.0.0'})} + api.option('ip_admin_eth0.ip_admin_eth0').value.pop(0) + assert api.value.get_modified() == {'ip_admin_eth0.ip_admin_eth0': ( + 'user', + ('192.168.230.146',)), + 'ip_admin_eth0.netmask_admin_eth0': ( + {'0': 'user'}, + {'0': '255.255.0.0'})} + assert api.option('ip_admin_eth0.ip_admin_eth0').value.get() == ["192.168.230.146"] + assert api.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get() == '255.255.0.0' + api.option('ip_admin_eth0.ip_admin_eth0').value.set(['192.168.230.146', "192.168.230.145", "192.168.230.146", "192.168.230.147", "192.168.230.148", "192.168.230.149"]) + api.option('ip_admin_eth0.netmask_admin_eth0', 3).value.set('255.255.0.0') + api.option('ip_admin_eth0.netmask_admin_eth0', 4).value.set('255.255.0.0') + assert api.value.get_modified() == {'ip_admin_eth0.ip_admin_eth0': ( + 'user', + ('192.168.230.146', "192.168.230.145", "192.168.230.146", "192.168.230.147", "192.168.230.148", "192.168.230.149")), + 'ip_admin_eth0.netmask_admin_eth0': ( + {'0': 'user', '3': 'user', '4': 'user'}, + {'0': '255.255.0.0', '3': '255.255.0.0', '4': '255.255.0.0'})} + api.option('ip_admin_eth0.ip_admin_eth0').value.pop(5) + assert api.value.get_modified() == {'ip_admin_eth0.ip_admin_eth0': ( + 'user', + ('192.168.230.146', "192.168.230.145", "192.168.230.146", "192.168.230.147", "192.168.230.148")), + 'ip_admin_eth0.netmask_admin_eth0': ( + {'0': 'user', '3': 'user', '4': 'user'}, + {'0': '255.255.0.0', '3': '255.255.0.0', '4': '255.255.0.0'})} + api.option('ip_admin_eth0.ip_admin_eth0').value.pop(2) + assert api.value.get_modified() == {'ip_admin_eth0.ip_admin_eth0': ( + 'user', + ('192.168.230.146', "192.168.230.145", "192.168.230.147", "192.168.230.148")), + 'ip_admin_eth0.netmask_admin_eth0': ( + {'0': 'user', '2': 'user', '3': 'user'}, + {'0': '255.255.0.0', '2': '255.255.0.0', '3': '255.255.0.0'})} + api.option('ip_admin_eth0.ip_admin_eth0').value.pop(2) + assert api.value.get_modified() == {'ip_admin_eth0.ip_admin_eth0': ('user', + ('192.168.230.146', + "192.168.230.145", + "192.168.230.148")), + 'ip_admin_eth0.netmask_admin_eth0': ({'0': 'user', '2': 'user'}, + {'0': '255.255.0.0', '2': '255.255.0.0'})} + api.option('ip_admin_eth0.ip_admin_eth0').value.pop(2) + assert api.value.get_modified() == {'ip_admin_eth0.ip_admin_eth0': ('user', + ('192.168.230.146', + "192.168.230.145")), + 'ip_admin_eth0.netmask_admin_eth0': ({'0': 'user'}, + {'0': '255.255.0.0'})} + + +def test_values_with_master_owner(): + 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 = MasterSlaves('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0]) + #interface1.impl_set_group_type(groups.master) + maconfig = OptionDescription('toto', '', [interface1]) + api = getapi(Config(maconfig)) + api.property.read_write() + owner = api.owner.get() + assert api.option('ip_admin_eth0.ip_admin_eth0').owner.isdefault() + api.option('ip_admin_eth0.ip_admin_eth0').value.set(["192.168.230.145"]) + assert api.option('ip_admin_eth0.ip_admin_eth0').owner.get() == owner + assert api.option('ip_admin_eth0.netmask_admin_eth0', 0).owner.isdefault() + api.option('ip_admin_eth0.ip_admin_eth0').value.pop(0) + assert api.option('ip_admin_eth0.ip_admin_eth0').owner.get() == owner + + +def test_values_with_master_disabled(): + 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 = MasterSlaves('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0]) + #interface1.impl_set_group_type(groups.master) + maconfig = OptionDescription('toto', '', [interface1]) + api = getapi(Config(maconfig)) + api.property.read_write() + api.option('ip_admin_eth0.ip_admin_eth0').value.set(["192.168.230.145"]) + api.option('ip_admin_eth0.ip_admin_eth0').value.pop(0) + api.option('ip_admin_eth0.ip_admin_eth0').value.set(["192.168.230.145"]) + api.option('ip_admin_eth0.netmask_admin_eth0', 0).value.set("192.168.230.145") + api.option('ip_admin_eth0.ip_admin_eth0').value.pop(0) + api.option('ip_admin_eth0.netmask_admin_eth0').property.add('disabled') + api.option('ip_admin_eth0.ip_admin_eth0').value.set(["192.168.230.145"]) + api.option('ip_admin_eth0.ip_admin_eth0').value.pop(0) + + #delete with value in disabled var + api.option('ip_admin_eth0.netmask_admin_eth0').property.pop('disabled') + api.option('ip_admin_eth0.ip_admin_eth0').value.set(["192.168.230.145"]) + api.option('ip_admin_eth0.netmask_admin_eth0', 0).value.set("192.168.230.145") + api.option('ip_admin_eth0.netmask_admin_eth0').property.add('disabled') + api.option('ip_admin_eth0.ip_admin_eth0').value.pop(0) + + #append with value in disabled var + api.option('ip_admin_eth0.netmask_admin_eth0').property.pop('disabled') + api.option('ip_admin_eth0.ip_admin_eth0').value.set(["192.168.230.145"]) + api.option('ip_admin_eth0.netmask_admin_eth0', 0).value.set("192.168.230.145") + api.option('ip_admin_eth0.netmask_admin_eth0').property.add('disabled') + api.option('ip_admin_eth0.ip_admin_eth0').value.set(["192.168.230.145", '192.168.230.43']) + + +def test_multi_non_valid_value(): + ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True) + maconfig = OptionDescription('toto', '', [ip_admin_eth0]) + api = getapi(Config(maconfig)) + api.property.read_write() + api.option('ip_admin_eth0').value.set(['a']) + raises(ValueError, "api.option('ip_admin_eth0').value.set([1])") + + +def test_multi_master_default_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", default_multi="255.255.255.0", multi=True) + interface1 = MasterSlaves('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0]) + #interface1.impl_set_group_type(groups.master) + maconfig = OptionDescription('toto', '', [interface1]) + api = getapi(Config(maconfig)) + api.property.read_write() + api.option('ip_admin_eth0.ip_admin_eth0').value.set(['192.168.1.1']) + assert api.option('ip_admin_eth0.ip_admin_eth0').value.get() == ['192.168.1.1'] + + +def test_groups_with_master_get_modified_value(): + 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 = MasterSlaves('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0]) + #interface1.impl_set_group_type(groups.master) + maconfig = OptionDescription('toto', '', [interface1]) + api = getapi(Config(maconfig)) + api.property.read_write() + assert api.value.get_modified() == {} + api.option('ip_admin_eth0.ip_admin_eth0').value.set(['192.168.1.1']) + assert api.value.get_modified() == {'ip_admin_eth0.ip_admin_eth0': ('user', ('192.168.1.1',))} + api.option('ip_admin_eth0.netmask_admin_eth0', 0).value.set('255.255.255.255') + assert api.value.get_modified() == {'ip_admin_eth0.ip_admin_eth0': ('user', ('192.168.1.1',)), 'ip_admin_eth0.netmask_admin_eth0': ({'0': 'user'}, {'0': '255.255.255.255'})} + api.option('ip_admin_eth0.ip_admin_eth0').value.set(['192.168.1.1', '192.168.1.1']) + api.option('ip_admin_eth0.netmask_admin_eth0', 1).value.set('255.255.255.255') + assert api.value.get_modified() == {'ip_admin_eth0.ip_admin_eth0': ('user', ('192.168.1.1', '192.168.1.1')), 'ip_admin_eth0.netmask_admin_eth0': ({'0': 'user', '1': 'user'}, {'0': '255.255.255.255', '1': '255.255.255.255'})} diff --git a/test/new_api/test_submulti.py b/test/new_api/test_submulti.py index 5e9f2d4..2ae345f 100644 --- a/test/new_api/test_submulti.py +++ b/test/new_api/test_submulti.py @@ -180,8 +180,8 @@ def test_groups_with_master_in_config_submulti(): 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=submulti) interface1 = MasterSlaves('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0]) - #interface1.impl_set_group_type(groups.master) - Config(interface1) + od = OptionDescription('root', '', [interface1]) + Config(od) assert interface1.impl_get_group_type() == groups.master @@ -246,7 +246,7 @@ def test_values_with_master_and_slaves_slave_submulti(): maconfig = OptionDescription('toto', '', [interface1]) api = getapi(Config(maconfig)) api.property.read_write() - raises(IndexError, "api.option('ip_admin_eth0.netmask_admin_eth0', 0).value.set(['255.255.255.0'])") + raises(SlaveError, "api.option('ip_admin_eth0.netmask_admin_eth0', 0).value.set(['255.255.255.0'])") api.option('ip_admin_eth0.ip_admin_eth0').value.set(['192.168.230.145']) api.option('ip_admin_eth0.netmask_admin_eth0', 0).value.set(['255.255.255.0']) api.option('ip_admin_eth0.netmask_admin_eth0', 0).value.set(['255.255.255.0', '255.255.255.0']) diff --git a/tiramisu/api.py b/tiramisu/api.py index 5866dae..a349ead 100644 --- a/tiramisu/api.py +++ b/tiramisu/api.py @@ -80,7 +80,22 @@ def display_count(): MOD_COUNT_TIME = deepcopy(COUNT_TIME) -class CommonTiramisuOption(object): +class CommonTiramisu(object): + allow_optiondescription = True + + def get_option(self): + option = self.config_bag.option + if option is None: + option = self.subconfig.cfgimpl_get_description().impl_getchild(self.name, + self.config_bag, + self.subconfig) + self.config_bag.option = option + if not self.allow_optiondescription and option.impl_is_optiondescription(): + raise APIError(_('option must not be an optiondescription')) + return option + + +class CommonTiramisuOption(CommonTiramisu): icon = '\u2937' tmpl_help = u' {} {}: {}' allow_unrestraint = False @@ -123,17 +138,6 @@ class CommonTiramisuOption(object): else: super(CommonTiramisuOption, self).__getattribute__(name) - def get_option(self): - option = self.config_bag.option - if option is None: - option = self.subconfig.cfgimpl_get_description().impl_getchild(self.name, - self.config_bag, - self.subconfig) - self.config_bag.option = option - if not self.allow_optiondescription and option.impl_is_optiondescription(): - raise APIError(_('option must not be an optiondescription')) - return option - def _help(self): txt = [] for func_name in dir(self): @@ -290,6 +294,7 @@ class TiramisuOptionProperty(CommonTiramisuOption): @count def add(self, prop): + #FIXME not index !! self.get_option() self.settings.addproperty(self.path, prop, @@ -402,12 +407,10 @@ class TiramisuOptionValue(CommonTiramisuOption): self.config_bag) @count - def pop(self, index): + def _pop(self, index): """pop value for a specified master values """ self.get_option() - self._test_slave_index() - #FIXME only for master self.config_bag.config.delattr(self.path, index, self.config_bag) @@ -422,8 +425,7 @@ class TiramisuOptionValue(CommonTiramisuOption): self.config_bag) @count - def len(self): - #FIXME only for slave + def _len(self): self.get_option() subconfig_path = self.path.rsplit('.', 1)[0] subconfig = self.config.getattr(subconfig_path, @@ -432,11 +434,12 @@ class TiramisuOptionValue(CommonTiramisuOption): return subconfig.cfgimpl_get_length() def __getattr__(self, name): - if name == 'list': - self.get_option() - if isinstance(self.config_bag.option, ChoiceOption): - return self._list - raise APIError(_('{} allowed only for choiceoption').format(name)) + if name == 'list' and isinstance(self.get_option(), ChoiceOption): + return self._list + elif name == 'pop' and self.get_option().impl_is_master_slaves('master'): + return self._pop + elif name == 'len' and self.get_option().impl_is_master_slaves('slave'): + return self._len raise APIError(_('{} is unknown').format(name)) @count @@ -452,7 +455,7 @@ def registers(registers, prefix): registers[func_name] = module -class TiramisuOption(object): +class TiramisuOption(CommonTiramisu): icon = '\u2937' tmpl_help = ' {} {}: {}' @@ -488,15 +491,21 @@ class TiramisuOption(object): self.config_bag) elif subfunc == 'help': return self._help() + elif subfunc == 'make_dict' and self.get_option().impl_is_optiondescription(): + return self._make_dict + elif subfunc == 'list' and self.get_option().impl_is_optiondescription(): + return self._list + elif subfunc == 'group_type' and self.get_option().impl_is_optiondescription(): + return self._group_type else: raise APIError(_('please specify a valid sub function ({})').format(subfunc)) @count - def make_dict(self, - flatten=False, - withvalue=undefined, - withoption=None, - fullpath=False): + def _make_dict(self, + flatten=False, + withvalue=undefined, + withoption=None, + fullpath=False): return self.config_bag.config.getattr(self.path, None, self.config_bag).make_dict(config_bag=self.config_bag, @@ -505,6 +514,25 @@ class TiramisuOption(object): withoption=withoption, withvalue=withvalue) + @count + def group_type(self): + return self.get_option().impl_get_group_type() + + @count + def _list(self, type='all', group_type=None): + if type == 'optiondescription': + return self.config_bag.config.getattr(self.path, + None, + self.config_bag + ).iter_groups(self.config_bag, group_type) + elif type == 'all': + return self.config_bag.config.getattr(self.path, + None, + self.config_bag + ).cfgimpl_get_children(self.config_bag) + else: + raise APIError(_('unknown list type {}').format(type)) + class TiramisuContext(object): def __init__(self, @@ -645,6 +673,15 @@ class TiramisuContextOption(TiramisuContext): withoption=withoption, withvalue=withvalue) + @count + def list(self, type='all', group_type=None): + if type == 'optiondescription': + return self.config_bag.config.iter_groups(self.config_bag, group_type) + elif type == 'all': + return self.config_bag.config.cfgimpl_get_children(self.config_bag) + else: + raise APIError(_('unknown list type {}').format(type)) + class TiramisuDispatcherOption(TiramisuContextOption): def __call__(self, path, index=None): diff --git a/tiramisu/config.py b/tiramisu/config.py index 6d7403b..258a53b 100644 --- a/tiramisu/config.py +++ b/tiramisu/config.py @@ -26,6 +26,7 @@ from copy import copy from .error import PropertiesOptionError, ConfigError, ConflictError, SlaveError from .option.syndynoptiondescription import SynDynOptionDescription +from .option.masterslave import MasterSlaves from .option.baseoption import BaseOption, valid_name from .setting import ConfigBag, groups, Settings, undefined from .storage import get_storages, get_default_values_storages @@ -198,9 +199,8 @@ class SubConfig(object): # pass # option with properties def iter_groups(self, - setting_properties, - group_type=None, - force_permissive=False): + config_bag, + group_type=None): """iteration on groups objects only. All groups are returned if `group_type` is `None`, otherwise the groups can be filtered by categories (families, or whatever). @@ -215,16 +215,34 @@ class SubConfig(object): context = self._cfgimpl_get_context() for child in self.cfgimpl_get_description().impl_getchildren(config_bag): if child.impl_is_optiondescription(): + nconfig_bag = config_bag.copy('nooption') + nconfig_bag.option = child try: if group_type is None or (group_type is not None and child.impl_get_group_type() == group_type): name = child.impl_getname() yield name, self.getattr(name, - force_permissive=force_permissive, - setting_properties=setting_properties) + None, + nconfig_bag) except PropertiesOptionError: # pragma: optional cover pass + + def cfgimpl_get_children(self, config_bag): + context = self._cfgimpl_get_context() + for opt in self.cfgimpl_get_description().impl_getchildren(config_bag): + nconfig_bag = config_bag.copy('nooption') + nconfig_bag.option = opt + name = opt.impl_getname() + subpath = self._get_subpath(name) + try: + context.cfgimpl_get_settings().validate_properties(subpath, + None, + nconfig_bag) + yield name + except PropertiesOptionError: + pass + # ______________________________________________________________________ # def __str__(self): @@ -300,9 +318,9 @@ class SubConfig(object): context.cfgimpl_get_settings().validate_properties(path, index, config_bag) - context.cfgimpl_get_description().impl_validate_value(config_bag.option, - value, - self) + self.cfgimpl_get_description().impl_validate_value(config_bag.option, + value, + self) return context.cfgimpl_get_values().setvalue(path, index, value, @@ -408,7 +426,7 @@ class SubConfig(object): '').format(subpath)) length = self.cfgimpl_get_length() if index is not None and index >= length: - raise IndexError(_('index "{}" is higher than the master length "{}" ' + raise SlaveError(_('index "{}" is higher than the master length "{}" ' 'for option "{}"').format(index, length, option.impl_get_display_name())) @@ -872,6 +890,8 @@ class Config(_CommonConfig): :type persistent: `boolean` """ self._impl_meta = None + if isinstance(descr, MasterSlaves): + raise ConfigError(_('cannot set MasterSlaves object has root optiondescription')) if force_settings is not None and force_values is not None: if isinstance(force_settings, tuple): self._impl_settings = Settings(self, diff --git a/tiramisu/option/masterslave.py b/tiramisu/option/masterslave.py index b853cbc..d6e97bb 100644 --- a/tiramisu/option/masterslave.py +++ b/tiramisu/option/masterslave.py @@ -172,8 +172,8 @@ class MasterSlaves(OptionDescription): context): if option.impl_is_master_slaves('master') and isinstance(value, list): if len(value) < context._impl_length: - raise ValueError(_('cannot reduce length of master "{}"' - '').format(option.impl_get_display_name())) + raise SlaveError(_('cannot reduce length of the master "{}"' + '').format(option.impl_get_display_name())) def is_masterslaves(self): return True