parsing_group

This commit is contained in:
Emmanuel Garette 2018-01-01 21:32:39 +01:00
parent b83b9dcaa6
commit 4d154a89b5
6 changed files with 695 additions and 44 deletions

View File

@ -252,8 +252,8 @@ def test_multi_with_requires_that_is_masterslave():
b = IntOption('int', 'Test int option', default=[0], multi=True) 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) c = StrOption('str', 'Test string option', requires=[{'option': b, 'expected': 1, 'action': 'hidden'}], multi=True)
descr = MasterSlaves("int", "", [b, c]) descr = MasterSlaves("int", "", [b, c])
#descr.impl_set_group_type(groups.master) od = OptionDescription('root', '', [descr])
Config(descr) Config(od)
def test_multi_with_requires_that_is_masterslave_master(): def test_multi_with_requires_that_is_masterslave_master():

View File

@ -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'})}

View File

@ -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) 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) 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 = MasterSlaves('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
#interface1.impl_set_group_type(groups.master) od = OptionDescription('root', '', [interface1])
Config(interface1) Config(od)
assert interface1.impl_get_group_type() == groups.master 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]) maconfig = OptionDescription('toto', '', [interface1])
api = getapi(Config(maconfig)) api = getapi(Config(maconfig))
api.property.read_write() 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.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'])
api.option('ip_admin_eth0.netmask_admin_eth0', 0).value.set(['255.255.255.0', '255.255.255.0']) api.option('ip_admin_eth0.netmask_admin_eth0', 0).value.set(['255.255.255.0', '255.255.255.0'])

View File

@ -80,7 +80,22 @@ def display_count():
MOD_COUNT_TIME = deepcopy(COUNT_TIME) 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' icon = '\u2937'
tmpl_help = u' {} {}: {}' tmpl_help = u' {} {}: {}'
allow_unrestraint = False allow_unrestraint = False
@ -123,17 +138,6 @@ class CommonTiramisuOption(object):
else: else:
super(CommonTiramisuOption, self).__getattribute__(name) 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): def _help(self):
txt = [] txt = []
for func_name in dir(self): for func_name in dir(self):
@ -290,6 +294,7 @@ class TiramisuOptionProperty(CommonTiramisuOption):
@count @count
def add(self, prop): def add(self, prop):
#FIXME not index !!
self.get_option() self.get_option()
self.settings.addproperty(self.path, self.settings.addproperty(self.path,
prop, prop,
@ -402,12 +407,10 @@ class TiramisuOptionValue(CommonTiramisuOption):
self.config_bag) self.config_bag)
@count @count
def pop(self, index): def _pop(self, index):
"""pop value for a specified master values """pop value for a specified master values
""" """
self.get_option() self.get_option()
self._test_slave_index()
#FIXME only for master
self.config_bag.config.delattr(self.path, self.config_bag.config.delattr(self.path,
index, index,
self.config_bag) self.config_bag)
@ -422,8 +425,7 @@ class TiramisuOptionValue(CommonTiramisuOption):
self.config_bag) self.config_bag)
@count @count
def len(self): def _len(self):
#FIXME only for slave
self.get_option() self.get_option()
subconfig_path = self.path.rsplit('.', 1)[0] subconfig_path = self.path.rsplit('.', 1)[0]
subconfig = self.config.getattr(subconfig_path, subconfig = self.config.getattr(subconfig_path,
@ -432,11 +434,12 @@ class TiramisuOptionValue(CommonTiramisuOption):
return subconfig.cfgimpl_get_length() return subconfig.cfgimpl_get_length()
def __getattr__(self, name): def __getattr__(self, name):
if name == 'list': if name == 'list' and isinstance(self.get_option(), ChoiceOption):
self.get_option() return self._list
if isinstance(self.config_bag.option, ChoiceOption): elif name == 'pop' and self.get_option().impl_is_master_slaves('master'):
return self._list return self._pop
raise APIError(_('{} allowed only for choiceoption').format(name)) elif name == 'len' and self.get_option().impl_is_master_slaves('slave'):
return self._len
raise APIError(_('{} is unknown').format(name)) raise APIError(_('{} is unknown').format(name))
@count @count
@ -452,7 +455,7 @@ def registers(registers, prefix):
registers[func_name] = module registers[func_name] = module
class TiramisuOption(object): class TiramisuOption(CommonTiramisu):
icon = '\u2937' icon = '\u2937'
tmpl_help = ' {} {}: {}' tmpl_help = ' {} {}: {}'
@ -488,15 +491,21 @@ class TiramisuOption(object):
self.config_bag) self.config_bag)
elif subfunc == 'help': elif subfunc == 'help':
return self._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: else:
raise APIError(_('please specify a valid sub function ({})').format(subfunc)) raise APIError(_('please specify a valid sub function ({})').format(subfunc))
@count @count
def make_dict(self, def _make_dict(self,
flatten=False, flatten=False,
withvalue=undefined, withvalue=undefined,
withoption=None, withoption=None,
fullpath=False): fullpath=False):
return self.config_bag.config.getattr(self.path, return self.config_bag.config.getattr(self.path,
None, None,
self.config_bag).make_dict(config_bag=self.config_bag, self.config_bag).make_dict(config_bag=self.config_bag,
@ -505,6 +514,25 @@ class TiramisuOption(object):
withoption=withoption, withoption=withoption,
withvalue=withvalue) 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): class TiramisuContext(object):
def __init__(self, def __init__(self,
@ -645,6 +673,15 @@ class TiramisuContextOption(TiramisuContext):
withoption=withoption, withoption=withoption,
withvalue=withvalue) 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): class TiramisuDispatcherOption(TiramisuContextOption):
def __call__(self, path, index=None): def __call__(self, path, index=None):

View File

@ -26,6 +26,7 @@ from copy import copy
from .error import PropertiesOptionError, ConfigError, ConflictError, SlaveError from .error import PropertiesOptionError, ConfigError, ConflictError, SlaveError
from .option.syndynoptiondescription import SynDynOptionDescription from .option.syndynoptiondescription import SynDynOptionDescription
from .option.masterslave import MasterSlaves
from .option.baseoption import BaseOption, valid_name from .option.baseoption import BaseOption, valid_name
from .setting import ConfigBag, groups, Settings, undefined from .setting import ConfigBag, groups, Settings, undefined
from .storage import get_storages, get_default_values_storages from .storage import get_storages, get_default_values_storages
@ -198,9 +199,8 @@ class SubConfig(object):
# pass # option with properties # pass # option with properties
def iter_groups(self, def iter_groups(self,
setting_properties, config_bag,
group_type=None, group_type=None):
force_permissive=False):
"""iteration on groups objects only. """iteration on groups objects only.
All groups are returned if `group_type` is `None`, otherwise the groups All groups are returned if `group_type` is `None`, otherwise the groups
can be filtered by categories (families, or whatever). can be filtered by categories (families, or whatever).
@ -215,16 +215,34 @@ class SubConfig(object):
context = self._cfgimpl_get_context() context = self._cfgimpl_get_context()
for child in self.cfgimpl_get_description().impl_getchildren(config_bag): for child in self.cfgimpl_get_description().impl_getchildren(config_bag):
if child.impl_is_optiondescription(): if child.impl_is_optiondescription():
nconfig_bag = config_bag.copy('nooption')
nconfig_bag.option = child
try: try:
if group_type is None or (group_type is not None and if group_type is None or (group_type is not None and
child.impl_get_group_type() child.impl_get_group_type()
== group_type): == group_type):
name = child.impl_getname() name = child.impl_getname()
yield name, self.getattr(name, yield name, self.getattr(name,
force_permissive=force_permissive, None,
setting_properties=setting_properties) nconfig_bag)
except PropertiesOptionError: # pragma: optional cover except PropertiesOptionError: # pragma: optional cover
pass 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): # def __str__(self):
@ -300,9 +318,9 @@ class SubConfig(object):
context.cfgimpl_get_settings().validate_properties(path, context.cfgimpl_get_settings().validate_properties(path,
index, index,
config_bag) config_bag)
context.cfgimpl_get_description().impl_validate_value(config_bag.option, self.cfgimpl_get_description().impl_validate_value(config_bag.option,
value, value,
self) self)
return context.cfgimpl_get_values().setvalue(path, return context.cfgimpl_get_values().setvalue(path,
index, index,
value, value,
@ -408,7 +426,7 @@ class SubConfig(object):
'').format(subpath)) '').format(subpath))
length = self.cfgimpl_get_length() length = self.cfgimpl_get_length()
if index is not None and index >= 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, 'for option "{}"').format(index,
length, length,
option.impl_get_display_name())) option.impl_get_display_name()))
@ -872,6 +890,8 @@ class Config(_CommonConfig):
:type persistent: `boolean` :type persistent: `boolean`
""" """
self._impl_meta = None 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 force_settings is not None and force_values is not None:
if isinstance(force_settings, tuple): if isinstance(force_settings, tuple):
self._impl_settings = Settings(self, self._impl_settings = Settings(self,

View File

@ -172,8 +172,8 @@ class MasterSlaves(OptionDescription):
context): context):
if option.impl_is_master_slaves('master') and isinstance(value, list): if option.impl_is_master_slaves('master') and isinstance(value, list):
if len(value) < context._impl_length: if len(value) < context._impl_length:
raise ValueError(_('cannot reduce length of master "{}"' raise SlaveError(_('cannot reduce length of the master "{}"'
'').format(option.impl_get_display_name())) '').format(option.impl_get_display_name()))
def is_masterslaves(self): def is_masterslaves(self):
return True return True