add force_metaconfig_on_freeze special properties

This commit is contained in:
Emmanuel Garette 2019-02-23 22:10:43 +01:00
parent c3f968dbde
commit 1bbcea60ab
8 changed files with 129 additions and 34 deletions

View file

@ -972,3 +972,64 @@ def test_meta_properties_meta_set_value():
assert isinstance(ret[0], ValueError)
del ret[0]
del ret
def test_metaconfig_force_metaconfig_on_freeze():
dummy1 = StrOption('dummy1', 'doc dummy', default='default')
dummy2 = StrOption('dummy2', 'doc dummy', default='default', properties=('force_default_on_freeze',))
group = OptionDescription('group', '', [dummy1, dummy2])
config = Config(group)
meta1 = MetaConfig([config], session_id='meta1')
meta1.owner.set(owners.meta1)
meta2 = MetaConfig([meta1], session_id='meta2')
meta2.owner.set(owners.meta2)
config.property.read_write()
config.option('dummy1').property.add('frozen')
config.option('dummy1').property.add('force_metaconfig_on_freeze')
config.option('dummy2').property.add('frozen')
#
assert config.option('dummy1').value.get() == 'default'
assert config.option('dummy1').owner.get() == 'default'
assert config.option('dummy2').value.get() == 'default'
assert config.option('dummy2').owner.get() == 'default'
#
meta2.option('dummy1').value.set('meta2')
meta2.option('dummy2').value.set('meta2')
#
assert config.option('dummy1').value.get() == 'meta2'
assert config.option('dummy1').owner.get() == 'meta2'
assert config.option('dummy2').value.get() == 'default'
assert config.option('dummy2').owner.get() == 'default'
#
config.option('dummy1').property.pop('frozen')
config.option('dummy2').property.pop('frozen')
config.option('dummy1').value.set('config')
config.option('dummy2').value.set('config')
config.option('dummy1').property.add('frozen')
config.option('dummy2').property.add('frozen')
#
assert config.option('dummy1').value.get() == 'meta2'
assert config.option('dummy1').owner.get() == 'meta2'
assert config.option('dummy2').value.get() == 'default'
assert config.option('dummy2').owner.get() == 'default'
#
meta1.option('dummy1').value.set('meta1')
meta1.option('dummy2').value.set('meta1')
#
assert config.option('dummy1').value.get() == 'meta1'
assert config.option('dummy1').owner.get() == 'meta1'
assert config.option('dummy2').value.get() == 'default'
assert config.option('dummy2').owner.get() == 'default'
#
meta1.option('dummy1').property.add('force_metaconfig_on_freeze')
assert config.option('dummy1').value.get() == 'meta2'
assert config.option('dummy1').owner.get() == 'meta2'
#
meta2.option('dummy1').property.add('force_metaconfig_on_freeze')
assert config.option('dummy1').value.get() == 'default'
assert config.option('dummy1').owner.get() == 'default'
#
meta1.option('dummy1').property.pop('force_metaconfig_on_freeze')
assert config.option('dummy1').value.get() == 'meta1'
assert config.option('dummy1').owner.get() == 'meta1'

View file

@ -120,6 +120,14 @@ def test_force_default_on_freeze_leader():
raises(ConfigError, "Config(descr)")
def test_force_metaconfig_on_freeze_leader():
dummy1 = BoolOption('dummy1', 'Test int option', multi=True, properties=('force_metaconfig_on_freeze',))
dummy2 = BoolOption('dummy2', 'Test string option', multi=True)
descr = Leadership("dummy1", "", [dummy1, dummy2])
descr = OptionDescription("root", "", [descr])
raises(ConfigError, "Config(descr)")
def test_force_default_on_freeze_leader_frozen():
dummy1 = BoolOption('dummy1', 'Test int option', multi=True, properties=('force_default_on_freeze', 'frozen'))
dummy2 = BoolOption('dummy2', 'Test string option', multi=True)
@ -129,6 +137,15 @@ def test_force_default_on_freeze_leader_frozen():
raises(ConfigError, "api.option('dummy1.dummy1').property.pop('frozen')")
def test_force_metaconfig_on_freeze_leader_frozen():
dummy1 = BoolOption('dummy1', 'Test int option', multi=True, properties=('force_metaconfig_on_freeze', 'frozen'))
dummy2 = BoolOption('dummy2', 'Test string option', multi=True)
descr = Leadership("dummy1", "", [dummy1, dummy2])
descr = OptionDescription("root", "", [descr])
api = Config(descr)
raises(ConfigError, "api.option('dummy1.dummy1').property.pop('frozen')")
def test_force_default_on_freeze_follower():
dummy1 = BoolOption('dummy1', 'Test int option', multi=True)
dummy2 = BoolOption('dummy2', 'Test string option', multi=True, properties=('force_default_on_freeze',))

View file

@ -185,6 +185,7 @@ def test_forbidden_permissive():
api = Config(descr)
api.property.read_write()
raises(ConfigError, "api.permissive.set(frozenset(['force_default_on_freeze']))")
raises(ConfigError, "api.permissive.set(frozenset(['force_metaconfig_on_freeze']))")
def test_permissive_option():

View file

@ -350,11 +350,11 @@ class TiramisuOptionProperty(CommonTiramisuOption):
raise ConfigError(_('cannot add this property: "{0}"').format(
' '.join(prop)))
props = self._settings.getproperties(self._option_bag,
apply_requires=False)
apply_requires=False)
self._settings.setproperties(self._option_bag.path,
props | {prop},
self._option_bag,
self._option_bag.config_bag.context)
props | {prop},
self._option_bag,
self._option_bag.config_bag.context)
def pop(self, prop):
"""Remove new property for an option"""

View file

@ -167,7 +167,7 @@ class Leadership(OptionDescription):
follower_path,
index,
config_bag)
# do not check force_default_on_freeze
# do not check force_default_on_freeze or force_metaconfig_on_freeze
soption_bag.properties = set()
if not values.is_default_owner(soption_bag,
validate_meta=False) and followerlen > index:

View file

@ -90,12 +90,15 @@ class CacheOptionDescription(BaseOption):
'"force_store_value" property').format(
option.impl_get_display_name()))
force_store_values.append((subpath, option))
if __debug__ and 'force_default_on_freeze' in properties and \
if __debug__ and ('force_default_on_freeze' in properties or \
'force_metaconfig_on_freeze' in properties) and \
'frozen' not in properties and \
option.impl_is_leader():
raise ConfigError(_('a leader ({0}) cannot have '
'"force_default_on_freeze" property without "frozen"'
'').format(subpath))
'"force_default_on_freeze" or '
'"force_metaconfig_on_freeze" '
'property without "frozen"'
'').format(option.impl_get_display_name()))
for cons_id, func, all_cons_opts, params in option.get_consistencies():
option._valid_consistencies(all_cons_opts[1:], init=False)
if func not in ALLOWED_CONST_LIST and is_multi:

View file

@ -113,6 +113,7 @@ RW_REMOVE = frozenset(['permissive', 'everything_frozen', 'mandatory',
FORBIDDEN_SET_PROPERTIES = frozenset(['force_store_value'])
FORBIDDEN_SET_PERMISSIVES = frozenset(['force_default_on_freeze',
'force_metaconfig_on_freeze',
'force_store_value'])
@ -164,11 +165,14 @@ class OptionBag:
def __delattr__(self, key):
if key in ['properties', 'permissives']:
try:
super().__delattr__(key)
except AttributeError:
pass
return
raise KeyError('unknown key {} for ConfigBag'.format(key)) # pragma: no cover
def copy(self):
kwargs = {}
option_bag = OptionBag()
for key in self.__slots__:
if key == 'properties' and self.config_bag is undefined:
@ -182,7 +186,7 @@ class ConfigBag:
'properties', # properties for current context
'true_properties', # properties for current context
'permissives', # permissives for current context
)
)
def __init__(self, context, **kwargs):
self.context = context
for key, value in kwargs.items():
@ -302,10 +306,10 @@ groups = GroupModule()
groups.default = groups.DefaultGroupType('default')
"""groups.leadership
leadership group is a special optiondescription, all suboptions should be
multi option and all values should have same length, to find leader's
option, the optiondescription's name should be same than de leader's
option"""
leadership group is a special optiondescription, all suboptions should
be multi option and all values should have same length, to find
leader's option, the optiondescription's name should be same than de
leader's option"""
groups.leadership = groups.LeadershipGroupType('leadership')
""" groups.family
@ -607,10 +611,9 @@ class Settings(object):
def set_context_properties(self,
properties,
context):
self.setproperties(None,
properties,
None,
context)
self._p_.setproperties(None,
properties)
context.cfgimpl_reset_cache(None)
def setproperties(self,
path,
@ -621,33 +624,29 @@ class Settings(object):
(never save properties if same has option properties)
"""
# should have index !!!
if path is not None and option_bag.option.impl_getrequires() is not None:
opt = option_bag.option
if opt.impl_getrequires() is not None:
not_allowed_props = properties & \
getattr(option_bag.option, '_calc_properties', static_set)
getattr(opt, '_calc_properties', static_set)
if not_allowed_props:
raise ValueError(_('cannot set property {} for option "{}" this property is '
'calculated').format(display_list(list(not_allowed_props),
add_quote=True),
option_bag.option.impl_get_display_name()))
if option_bag is None:
opt = None
else:
opt = option_bag.option
if opt and opt.impl_is_symlinkoption():
opt.impl_get_display_name()))
if opt.impl_is_symlinkoption():
raise TypeError(_("can't assign property to the symlinkoption \"{}\""
"").format(opt.impl_get_display_name()))
if 'force_default_on_freeze' in properties and \
if ('force_default_on_freeze' in properties or 'force_metaconfig_on_freeze' in properties) and \
'frozen' not in properties and \
opt.impl_is_leader():
raise ConfigError(_('a leader ({0}) cannot have '
'"force_default_on_freeze" property without "frozen"'
'"force_default_on_freeze" or "force_metaconfig_on_freeze" property without "frozen"'
'').format(opt.impl_get_display_name()))
self._p_.setproperties(path,
properties)
# values too because of follower values could have a PropertiesOptionError has value
context.cfgimpl_reset_cache(option_bag)
if option_bag is not None:
del option_bag.properties
del option_bag.properties
def set_context_permissives(self,
permissives):

View file

@ -114,10 +114,12 @@ class Values(object):
owners.default,
index=_index,
with_value=True)
if owner != owners.default and not ('frozen' in option_bag.properties and \
'force_default_on_freeze' in option_bag.properties):
if owner != owners.default and \
not ('frozen' in option_bag.properties and 'force_default_on_freeze' in option_bag.properties) and \
not ('frozen' in option_bag.properties and 'force_metaconfig_on_freeze' in option_bag.properties):
# if a value is store in storage, check if not frozen + force_default_on_freeze
# if frozen + force_default_on_freeze => force default value
# if frozen + force_metaconfig_on_freeze => force value of metaconfig
return value
return self.getdefaultvalue(option_bag)
@ -325,8 +327,17 @@ class Values(object):
doption_bag = option_bag.copy()
config_bag = option_bag.config_bag.copy()
config_bag.context = meta
config_bag.unrestraint()
doption_bag.config_bag = config_bag
if 'force_metaconfig_on_freeze' in option_bag.properties:
# remove force_metaconfig_on_freeze only if option in metaconfig
# hasn't force_metaconfig_on_freeze properties
ori_properties = doption_bag.properties
del doption_bag.properties
if 'force_metaconfig_on_freeze' not in doption_bag.properties:
doption_bag.properties = ori_properties - {'force_metaconfig_on_freeze'}
else:
doption_bag.properties = ori_properties
config_bag.unrestraint()
meta_option_bag = meta.cfgimpl_get_values().getowner(doption_bag,
only_default=True)
if meta_option_bag == owners.default:
@ -378,11 +389,14 @@ class Values(object):
owner = self._p_.getowner(option_bag.path,
owners.default,
index=option_bag.index)
if owner is owners.default and validate_meta is not False:
if validate_meta is not False and (owner is owners.default or \
'force_metaconfig_on_freeze' in option_bag.properties):
moption_bag = self._get_meta(option_bag)
if moption_bag:
owner = moption_bag.config_bag.context.cfgimpl_get_values().getowner(moption_bag,
only_default=only_default)
elif 'force_metaconfig_on_freeze' in option_bag.properties:
return owners.default
return owner
def setowner(self,