diff --git a/tests/test_leadership.py b/tests/test_leadership.py index 0e2c12d..54c80fd 100644 --- a/tests/test_leadership.py +++ b/tests/test_leadership.py @@ -194,7 +194,7 @@ def test_groups_is_leader(config_type): assert not cfg.option('leadership.netmask_admin_eth0').isleader() assert cfg.option('leadership.netmask_admin_eth0').isfollower() assert cfg.option('leadership.netmask_admin_eth0').path() == 'leadership.netmask_admin_eth0' - assert cfg.option('leadership.netmask_admin_eth0').defaultmulti() == 'value' + assert cfg.option('leadership.netmask_admin_eth0').value.defaultmulti() == 'value' if config_type == 'tiramisu-api': cfg.send() # assert not list_sessions() diff --git a/tests/test_option_callback.py b/tests/test_option_callback.py index 3fecf0f..2d5b047 100644 --- a/tests/test_option_callback.py +++ b/tests/test_option_callback.py @@ -294,7 +294,7 @@ def test_callback(config_type): cfg.option('val1').value.set('new-val') assert cfg.option('val1').value.get() == 'new-val' with pytest.raises(ConfigError): - assert cfg.option('val1').defaultmulti() == None + assert cfg.option('val1').value.defaultmulti() == None cfg.option('val1').value.reset() assert cfg.option('val1').value.get() == 'val' # assert not list_sessions() @@ -548,7 +548,7 @@ def test_callback_multi(config_type): cfg = get_config(cfg, config_type) assert cfg.option('val1').value.get() == ['val'] cfg.option('val1').value.set(['new-val']) - assert cfg.option('val1').defaultmulti() == None + assert cfg.option('val1').value.defaultmulti() == None assert cfg.option('val1').value.get() == ['new-val'] cfg.option('val1').value.set(['new-val', 'new-val2']) assert cfg.option('val1').value.get() == ['new-val', 'new-val2'] @@ -963,7 +963,7 @@ def test_callback_leader_and_followers_leader_list(config_type): assert cfg.option('val1.val1').value.get() == ['val', 'val'] assert cfg.option('val1.val2', 0).value.get() == None assert cfg.option('val1.val2', 1).value.get() == None - default_multi = cfg.option('val1.val1').defaultmulti() + default_multi = cfg.option('val1.val1').value.defaultmulti() cfg.option('val1.val1').value.set(['val', 'val', default_multi]) assert cfg.option('val1.val1').value.get() == ['val', 'val', None] assert cfg.option('val1.val2', 0).value.get() == None diff --git a/tests/test_option_setting.py b/tests/test_option_setting.py index 884915b..490260f 100644 --- a/tests/test_option_setting.py +++ b/tests/test_option_setting.py @@ -514,10 +514,10 @@ def test_accepts_multiple_changes_from_option(): od1 = OptionDescription("options", "", [s]) cfg = Config(od1) cfg.option('string').value.set("egg") - assert cfg.option('string').default() == "string" + assert cfg.option('string').value.default() == "string" assert cfg.option('string').value.get() == "egg" cfg.option('string').value.set('blah') - assert cfg.option('string').default() == "string" + assert cfg.option('string').value.default() == "string" assert cfg.option('string').value.get() == "blah" cfg.option('string').value.set('bol') assert cfg.option('string').value.get() == 'bol' diff --git a/tests/test_submulti.py b/tests/test_submulti.py index 86b45a6..c76ee6b 100644 --- a/tests/test_submulti.py +++ b/tests/test_submulti.py @@ -115,18 +115,18 @@ def test_append_submulti(): # assert cfg.option('multi2').value.get() == [] assert cfg.option('multi2').owner.get() == owners.default - cfg.option('multi2').value.set([cfg.option('multi2').defaultmulti()]) + cfg.option('multi2').value.set([cfg.option('multi2').value.defaultmulti()]) assert cfg.option('multi2').owner.get() == owner assert cfg.option('multi2').value.get() == [['yes']] - cfg.option('multi2').value.set([cfg.option('multi2').defaultmulti(), ['no']]) + cfg.option('multi2').value.set([cfg.option('multi2').value.defaultmulti(), ['no']]) assert cfg.option('multi2').value.get() == [['yes'], ['no']] # assert cfg.option('multi3').value.get() == [['yes']] assert cfg.option('multi3').owner.get() == owners.default - cfg.option('multi3').value.set([cfg.option('multi2').defaultmulti(), []]) + cfg.option('multi3').value.set([cfg.option('multi2').value.defaultmulti(), []]) assert cfg.option('multi3').owner.get() == owner assert cfg.option('multi3').value.get() == [['yes'], []] - cfg.option('multi3').value.set([cfg.option('multi2').defaultmulti(), [], ['no']]) + cfg.option('multi3').value.set([cfg.option('multi2').value.defaultmulti(), [], ['no']]) assert cfg.option('multi3').value.get() == [['yes'], [], ['no']] # assert not list_sessions() @@ -193,7 +193,7 @@ def test_callback_submulti_str(): owner = cfg.owner.get() assert cfg.option('multi').owner.get() == owners.default assert cfg.option('multi').value.get() == [['val']] - cfg.option('multi').value.set([['val'], cfg.option('multi').defaultmulti()]) + cfg.option('multi').value.set([['val'], cfg.option('multi').value.defaultmulti()]) assert cfg.option('multi').owner.get() == owner assert cfg.option('multi').value.get() == [['val'], ['val']] cfg.option('multi').value.reset() @@ -209,10 +209,10 @@ def test_callback_submulti_list(): owner = cfg.owner.get() assert cfg.option('multi').value.get() == [['val', 'val']] assert cfg.option('multi').owner.get() == owners.default - cfg.option('multi').value.set([['val', 'val'], cfg.option('multi').defaultmulti()]) + cfg.option('multi').value.set([['val', 'val'], cfg.option('multi').value.defaultmulti()]) assert cfg.option('multi').owner.get() == owner assert cfg.option('multi').value.get() == [['val', 'val'], ['val', 'val']] - cfg.option('multi').value.set([['val', 'val'], cfg.option('multi').defaultmulti(), cfg.option('multi').defaultmulti()]) + cfg.option('multi').value.set([['val', 'val'], cfg.option('multi').value.defaultmulti(), cfg.option('multi').value.defaultmulti()]) assert cfg.option('multi').value.get() == [['val', 'val'], ['val', 'val'], ['val', 'val']] cfg.option('multi').value.reset() assert cfg.option('multi').owner.get() == owners.default @@ -227,7 +227,7 @@ def test_callback_submulti_list_list(): owner = cfg.owner.get() assert cfg.option('multi').value.get() == [['val', 'val']] assert cfg.option('multi').owner.get() == owners.default - cfg.option('multi').value.set([['val', 'val'], cfg.option('multi').defaultmulti()]) + cfg.option('multi').value.set([['val', 'val'], cfg.option('multi').value.defaultmulti()]) assert cfg.option('multi').owner.get() == owner assert cfg.option('multi').value.get() == [['val', 'val'], []] cfg.option('multi').value.reset() diff --git a/tests/test_symlink.py b/tests/test_symlink.py index f2fc5ce..908b271 100644 --- a/tests/test_symlink.py +++ b/tests/test_symlink.py @@ -54,17 +54,13 @@ def test_symlink_default(config_type): assert not cfg.option('c').ismulti() assert not cfg.option('s1.b').issubmulti() assert not cfg.option('c').issubmulti() - assert not cfg.option('s1.b').default() - assert not cfg.option('c').default() assert not cfg.option('s1.b').value.default() assert not cfg.option('c').value.default() with pytest.raises(ConfigError): - assert not cfg.option('s1.b').defaultmulti() + assert not cfg.option('s1.b').value.defaultmulti() with pytest.raises(ConfigError): - assert not cfg.option('c').defaultmulti() + assert not cfg.option('c').value.defaultmulti() cfg.option("s1.b").value.set(True) - assert not cfg.option('s1.b').default() - assert not cfg.option('c').default() assert not cfg.option('s1.b').value.default() assert not cfg.option('c').value.default() ## assert not list_sessions() @@ -82,19 +78,15 @@ def test_symlink_default_multi(config_type): assert cfg.option('c').ismulti() assert not cfg.option('s1.b').issubmulti() assert not cfg.option('c').issubmulti() - assert cfg.option('s1.b').default() == [False] - assert cfg.option('c').default() == [False] assert cfg.option('s1.b').value.default() == [False] assert cfg.option('c').value.default() == [False] - assert cfg.option('s1.b').defaultmulti() - assert cfg.option('c').defaultmulti() + assert cfg.option('s1.b').value.defaultmulti() + assert cfg.option('c').value.defaultmulti() cfg.option("s1.b").value.set([True]) - assert cfg.option('s1.b').default() == [False] - assert cfg.option('c').default() == [False] assert cfg.option('s1.b').value.default() == [False] assert cfg.option('c').value.default() == [False] - assert cfg.option('s1.b').defaultmulti() - assert cfg.option('c').defaultmulti() + assert cfg.option('s1.b').value.defaultmulti() + assert cfg.option('c').value.defaultmulti() ## assert not list_sessions() diff --git a/tiramisu/api.py b/tiramisu/api.py index d92c815..3c0ec22 100644 --- a/tiramisu/api.py +++ b/tiramisu/api.py @@ -83,15 +83,20 @@ class TiramisuHelp: return list(self._registers.keys()) return super().__dir__() + def __getattr__(self, subfunc): + raise ConfigError(_(f'please specify a valid sub function ({self.__class__.__name__}.{subfunc})')) + class CommonTiramisu(TiramisuHelp): _validate_properties = True + _allow_dynoption = False def _set_subconfig(self) -> None: self._subconfig = self._config_bag.context.get_sub_config(self._config_bag, self._path, self._index, validate_properties=False, + allow_dynoption=self._allow_dynoption, ) @@ -155,7 +160,7 @@ def option_type(typ): msg = _('please specify index with a follower option ' f'({self.__class__.__name__}.{func.__name__})') raise ConfigError(msg) - if self._validate_properties: + if self._validate_properties and 'dont_validate_property' not in types: settings = self._config_bag.context.get_settings() parent = self._subconfig.parent if parent and parent.transitive_properties: @@ -191,9 +196,6 @@ class CommonTiramisuOption(CommonTiramisu): self._config_bag = config_bag self._set_subconfig() - def __getattr__(self, subfunc): - raise ConfigError(_(f'please specify a valid sub function ({self.__class__.__name__}.{subfunc})')) - class _TiramisuOptionWalk: def _list(self, @@ -278,6 +280,7 @@ class _TiramisuOptionOptionDescription: options.append(TiramisuOption(option().impl_getpath(), None, self._config_bag, + allow_dynoption=True, )) return options @@ -381,18 +384,6 @@ class _TiramisuOptionOption(_TiramisuOptionOptionDescription): """Test if option is a symlink option""" return self._subconfig.option.impl_is_symlinkoption() - @option_type(['option', 'with_or_without_index', 'symlink']) - def default(self): - """Get default value for an option (not for optiondescription)""" - return self._subconfig.option.impl_getdefault() - - @option_type(['option', 'with_or_without_index', 'symlink']) - def defaultmulti(self): - """Get default value when added a value for a multi option (not for optiondescription)""" - if not self._subconfig.option.impl_is_multi(): - raise ConfigError(_('only multi value has defaultmulti')) - return self._subconfig.option.impl_getdefault_multi() - @option_type(['option', 'with_or_without_index']) def pattern(self) -> str: """Get the option pattern""" @@ -702,11 +693,28 @@ class TiramisuOptionValue(CommonTiramisuOption, _TiramisuODGet): else: values.reset(self._subconfig) - @option_type(['option', 'with_index', 'symlink']) - def default(self): + @option_type(['option', 'with_or_without_index', 'symlink', "dont_validate_property"]) + def default(self, + uncalculated: bool=False, + ) -> Any: """Get default value (default of option or calculated value)""" + if uncalculated: + return self._subconfig.option.impl_getdefault() + if self._subconfig.option.impl_is_follower() and self._subconfig.index is None: + msg = _('please specify index with a follower option ' + f'({self.__class__.__name__}.{func.__name__})') + raise ConfigError(msg) + if 'force_store_value' in self._subconfig.properties and 'force_store_value' in self._config_bag.properties: + return self._get(self._subconfig) return self._config_bag.context.get_values().get_default_value(self._subconfig) + @option_type(['option', 'with_or_without_index', 'symlink', "dont_validate_property"]) + def defaultmulti(self): + """Get default value when added a value for a multi option (not for optiondescription)""" + if not self._subconfig.option.impl_is_multi(): + raise ConfigError(_('only multi value has defaultmulti')) + return self._subconfig.option.impl_getdefault_multi() + @option_type(['option', 'with_index']) def valid(self): """The if the option's value is valid""" @@ -794,15 +802,16 @@ class TiramisuOption(CommonTiramisu, config_bag: Optional[ConfigBag]=None, *, subconfig: Optional[SubConfig]=None, + allow_dynoption: bool=False, ) -> None: self._path = path self._index = index self._config_bag = config_bag + self._allow_dynoption = allow_dynoption if subconfig is None: self._set_subconfig() else: self._subconfig = subconfig - self._tiramisu_dict = None if not self._registers: _registers(self._registers, 'TiramisuOption') @@ -1192,7 +1201,7 @@ class TiramisuContextProperty(TiramisuConfig, PropertyPermissive): if type is None and when is None: return DEFAULT_PROPERTIES if type == 'current': - return setting.get_context_properties(self._config_bag.context.properties_cache) + return setting.get_context_properties() if when not in ['append', 'remove']: raise ValueError(_('unknown when {} (must be in append or remove)').format(when)) if type == 'read_only': @@ -1267,11 +1276,8 @@ class TiramisuContextPermissive(TiramisuConfig, PropertyPermissive): class TiramisuContextOption(TiramisuConfig, _TiramisuOptionWalk): - def __init__(self, - *args, - **kwargs) -> None: + def __init__(self) -> None: self._tiramisu_dict = None - super().__init__(*args, **kwargs) def __iter__(self): root = self._config_bag.context.get_root(self._config_bag) @@ -1529,6 +1535,7 @@ class TiramisuAPI(TiramisuHelp): self._orig_config_bags = orig_config_bags if not self._registers: _registers(self._registers, 'TiramisuContext') + super().__init__() def option(self, path: str, diff --git a/tiramisu/config.py b/tiramisu/config.py index 5ce7947..f7651dc 100644 --- a/tiramisu/config.py +++ b/tiramisu/config.py @@ -624,6 +624,7 @@ class _Config(CCache): validate_properties: bool=True, properties=undefined, true_path: Optional[str]=None, + allow_dynoption: bool=False, ): subconfig = self.get_root(config_bag) if path is None: @@ -649,6 +650,7 @@ class _Config(CCache): config_bag, subconfig, with_suffix=True, + allow_dynoption=allow_dynoption, ) if isinstance(option, tuple): suffix, option = option diff --git a/tiramisu/setting.py b/tiramisu/setting.py index 6c45595..5dcbf0a 100644 --- a/tiramisu/setting.py +++ b/tiramisu/setting.py @@ -616,7 +616,7 @@ class Settings: apply_requires=True, uncalculated=False, transitive_raise=True, - not_unrestraint=False, + not_unrestraint: bool=False, ): """raise if needed """ @@ -653,7 +653,7 @@ class Settings: def _calc_raises_properties(self, subconfig, option_properties, - not_unrestraint, + not_unrestraint: bool, ): config_bag = subconfig.config_bag if not_unrestraint and config_bag.is_unrestraint: