requires for a master is a required for the masterslaves + remove cache from masterslaves too

This commit is contained in:
Emmanuel Garette 2018-09-02 11:55:19 +02:00
parent 71ec5b7148
commit 122796bd19
9 changed files with 101 additions and 25 deletions

View File

@ -446,8 +446,7 @@ def test_cache_master_and_slaves_master():
compare(cfg._config.cfgimpl_get_values()._p_.get_cached(), {'val1.val1': {None: ([], None)}})
#
cfg.option('val1.val1').value.set([undefined])
compare(cfg._config.cfgimpl_get_settings()._p_.get_cached(), {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)},
'val1': {None: (set([]), None)}})
compare(cfg._config.cfgimpl_get_settings()._p_.get_cached(), {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)}})
assert cfg._config.cfgimpl_get_values()._p_.get_cached() == {}
cfg.config.dict()
if TIRAMISU_VERSION == 2:
@ -467,8 +466,7 @@ def test_cache_master_and_slaves_master():
cfg.option('val1.val1').value.set([undefined, undefined])
cfg.config.dict()
cfg.option('val1.val2', 1).value.set('oui')
compare(cfg._config.cfgimpl_get_settings()._p_.get_cached(), {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)},
'val1': {None: (set([]), None)}})
compare(cfg._config.cfgimpl_get_settings()._p_.get_cached(), {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)}})
assert cfg._config.cfgimpl_get_values()._p_.get_cached() == {}
if TIRAMISU_VERSION == 2:
val1_val2_props = {None: (set([]), None), 0: (set([]), None), 1: (set([]), None)}
@ -520,8 +518,7 @@ def test_cache_master_callback():
'val1.val2': {None: (val1_val2_props, None)}})
compare(cfg._config.cfgimpl_get_values()._p_.get_cached(), {'val1.val1': {None: ([], None)}})
cfg.option('val1.val1').value.set([undefined])
compare(cfg._config.cfgimpl_get_settings()._p_.get_cached(), {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)},
'val1': {None: (set([]), None)}})
compare(cfg._config.cfgimpl_get_settings()._p_.get_cached(), {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)}})
assert cfg._config.cfgimpl_get_values()._p_.get_cached() == {}
cfg.config.dict()

View File

@ -970,6 +970,62 @@ def test_master_slave_requires():
assert isinstance(ret['ip_admin_eth0.netmask_admin_eth0'][1], PropertiesOptionError)
def test_master_slave_requires_master():
activate = BoolOption('activate', "Activer l'accès au réseau", True)
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True,
requires=[{'option': activate, 'expected': False, 'action': 'disabled'}])
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', '', [activate, interface1])
api = Config(maconfig)
api.property.read_write()
#
assert api.option('ip_admin_eth0.ip_admin_eth0').value.get() == []
api.option('ip_admin_eth0.ip_admin_eth0').value.set(['192.168.1.2'])
assert api.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get() is None
assert api.option('ip_admin_eth0.ip_admin_eth0').value.get() == ['192.168.1.2']
#
api.option('activate').value.set(False)
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()")
#
api.option('activate').value.set(True)
assert api.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get() is None
#
api.option('activate').value.set(False)
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()")
assert api.config.dict() == {'activate': False}
def test_master_slave_requires_masterslaves():
activate = BoolOption('activate', "Activer l'accès au réseau", True)
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True)
interface1 = MasterSlaves('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0],
requires=[{'option': activate, 'expected': False, 'action': 'disabled'}])
maconfig = OptionDescription('toto', '', [activate, interface1])
api = Config(maconfig)
api.property.read_write()
#
assert api.option('ip_admin_eth0.ip_admin_eth0').value.get() == []
api.option('ip_admin_eth0.ip_admin_eth0').value.set(['192.168.1.2'])
assert api.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get() is None
assert api.option('ip_admin_eth0.ip_admin_eth0').value.get() == ['192.168.1.2']
#
api.option('activate').value.set(False)
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()")
#
api.option('activate').value.set(True)
assert api.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get() is None
#
api.option('activate').value.set(False)
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()")
assert api.config.dict() == {'activate': False}
def test_master_slave_requires_no_master():
activate = BoolOption('activate', "Activer l'accès au réseau", True)
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)

View File

@ -24,9 +24,7 @@ from copy import copy
from .error import PropertiesOptionError, ConfigError, ConflictError, SlaveError
from .option.syndynoptiondescription import SynDynOptionDescription
from .option.dynoptiondescription import DynOptionDescription
from .option.masterslave import MasterSlaves
from .option import SynDynOptionDescription, DynOptionDescription, MasterSlaves
from .option.baseoption import BaseOption, valid_name
from .setting import OptionBag, ConfigBag, groups, Settings, undefined
from .storage import get_storages, get_default_values_storages

View File

@ -1,7 +1,7 @@
from .optiondescription import OptionDescription
from .dynoptiondescription import DynOptionDescription
from .syndynoptiondescription import SynDynOptionDescription
from .masterslave import MasterSlaves
from .masterslaves import MasterSlaves
from .baseoption import submulti
from .symlinkoption import SymLinkOption
from .dynsymlinkoption import DynSymLinkOption

View File

@ -98,11 +98,7 @@ class Base(object):
raise TypeError(_('invalid properties type {0} for {1},'
' must be a frozenset').format(type(properties),
name))
if calc_properties != frozenset([]) and properties:
set_forbidden_properties = calc_properties & properties
if set_forbidden_properties != frozenset():
raise ValueError(_('conflict: properties already set in '
'requirement {0}').format(display_list(list(set_forbidden_properties))))
self.validate_properties(name, calc_properties, properties)
_setattr = object.__setattr__
_setattr(self, '_name', name)
_setattr(self, '_informations', {'doc': doc})
@ -113,6 +109,13 @@ class Base(object):
if properties:
_setattr(self, '_properties', properties)
def validate_properties(self, name, calc_properties, properties):
set_forbidden_properties = calc_properties & properties
if set_forbidden_properties != frozenset():
raise ValueError(_('conflict: properties already set in requirement {0} for {1}'
'').format(display_list(list(set_forbidden_properties)),
name))
def _get_function_args(self,
function):
args = set()

View File

@ -111,7 +111,7 @@ class IPOption(Option):
raise ValueError(msg.format(network,
netmask,
opts[1].impl_get_display_name(),
opts[2].impl_getname(),
opts[2].impl_get_display_name(),
ip))
# test if ip is not network/broadcast IP
opts[2]._cons_ip_netmask(current_opt,

View File

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
"master slave support"
"master slaves support"
# Copyright (C) 2014-2018 Team tiramisu (see AUTHORS for all contributors)
#
# This program is free software: you can redistribute it and/or modify it
@ -27,7 +27,7 @@ from ..i18n import _
from ..setting import groups, undefined, OptionBag
from .optiondescription import OptionDescription
from .option import Option
from ..error import SlaveError, PropertiesOptionError
from ..error import SlaveError, PropertiesOptionError, RequirementError
from ..function import ParamOption
@ -69,9 +69,9 @@ class MasterSlaves(OptionDescription):
self.impl_get_display_name()))
# no empty property for save
if idx != 0:
properties = list(child._properties)
properties.remove('empty')
child._properties = frozenset(properties)
child_properties = list(child._properties)
child_properties.remove('empty')
child._properties = frozenset(child_properties)
slaves.append(child)
child._add_dependency(self)
child._master_slaves = weakref.ref(self)
@ -82,6 +82,21 @@ class MasterSlaves(OptionDescription):
if callbk.option in slaves:
raise ValueError(_("callback of master's option shall "
"not refered a slave's ones"))
# master should not have requires, only MasterSlaves should have
# so move requires to MasterSlaves
# if MasterSlaves has requires to, cannot manage the move so raises
master_requires = getattr(master, '_requires', None)
if master_requires:
if self.impl_getrequires():
raise RequirementError(_('master {} in MasterSlaves {} cannot have both requirement'
'').format(master.impl_getname(),
self.impl_getname()))
master_calproperties = getattr(master, '_calc_properties', None)
if master_calproperties:
if properties is not None:
self.validate_properties(name, master_calproperties, frozenset(properties))
setattr(self, '_calc_properties', master_calproperties)
setattr(self, '_requires', master_requires)
def is_master(self, opt):
master = self._children[0][0]
@ -158,18 +173,24 @@ class MasterSlaves(OptionDescription):
resetted_opts):
master = self.getmaster()
slaves = self.getslaves()
self._reset_cache(master,
self._reset_cache(path,
master,
slaves,
values,
settings,
resetted_opts)
def _reset_cache(self,
path,
master,
slaves,
values,
settings,
resetted_opts):
super().reset_cache(path,
values,
settings,
resetted_opts)
context = values._getcontext()
mpath = master.impl_getpath(context)
master.reset_cache(mpath,

View File

@ -673,9 +673,9 @@ class Option(OnlyOption):
log.debug(_('_cons_not_equal: {} are not different').format(display_list(equal)))
if is_current:
if warnings_only:
msg = _('should be different from the value of {}')
msg = _('should be different from the value of "{}"')
else:
msg = _('must be different from the value of {}')
msg = _('must be different from the value of "{}"')
else:
if warnings_only:
msg = _('value for {} should be different')

View File

@ -103,7 +103,8 @@ class SynDynOptionDescription(object):
if self.impl_get_group_type() == groups.master:
master = self.getmaster()
slaves = self.getslaves()
self._reset_cache(master,
self._reset_cache(path,
master,
slaves,
values,
settings,