From a3261abc94d615f8a03ebb33b2af1d6277d06433 Mon Sep 17 00:00:00 2001 From: Emmanuel Garette Date: Sat, 4 Nov 2023 08:27:22 +0100 Subject: [PATCH] if an option has configerror for mandatory property but is disabled too, do not raise --- tests/test_mandatory.py | 13 +++++- tiramisu/setting.py | 87 ++++++++++++++++++++++++----------------- 2 files changed, 63 insertions(+), 37 deletions(-) diff --git a/tests/test_mandatory.py b/tests/test_mandatory.py index 501d09a..bfb889c 100644 --- a/tests/test_mandatory.py +++ b/tests/test_mandatory.py @@ -5,7 +5,7 @@ do_autopath() import pytest from tiramisu import Config -from tiramisu import IntOption, StrOption, OptionDescription, DynOptionDescription, \ +from tiramisu import IntOption, StrOption, OptionDescription, DynOptionDescription, PasswordOption, UsernameOption, \ SymLinkOption, Leadership, undefined, Calculation, Params, \ ParamOption, ParamValue, ParamIndex, calc_value from tiramisu.error import PropertiesOptionError, ConfigError @@ -14,6 +14,8 @@ from tiramisu.setting import groups #def teardown_function(function): # assert list_sessions() == [], 'session list is not empty when leaving "{}"'.format(function.__name__) +def is_mandatory(variable): + return True def make_description(): @@ -723,3 +725,12 @@ def test_mandatory_callback_leader_and_followers_leader(): # FIXME cfg = get_config(cfg, config_type) compare(cfg.value.mandatory(), ['val1.val1']) # assert not list_sessions() + + +def test_mandatory_and_disabled(): + password = PasswordOption(name="password", doc="Password", properties=frozenset({"disabled"})) + username = UsernameOption(name="username", doc="Username", properties=frozenset({"normal", Calculation(is_mandatory, Params((ParamOption(password)))), "disabled"})) + od1 = OptionDescription('rootconfig', '', [username, password]) + cfg = Config(od1) + cfg.property.read_write() + cfg.value.dict() diff --git a/tiramisu/setting.py b/tiramisu/setting.py index fb463b8..5209b72 100644 --- a/tiramisu/setting.py +++ b/tiramisu/setting.py @@ -196,9 +196,12 @@ class OptionBag: self.properties = None elif properties is undefined: settings = context.get_settings() - self.properties = settings.getproperties(self, - apply_requires=apply_requires, - ) + try: + self.properties = settings.getproperties(self, + apply_requires=apply_requires, + ) + except ConfigError: + self.properties = None if properties is not undefined: self.properties = properties @@ -454,6 +457,7 @@ class Settings: apply_requires=True, uncalculated=False, help_property=False, + transitive_raise=True, ): """get properties """ @@ -489,17 +493,22 @@ class Settings: else: props.add((prop, prop)) elif apply_requires: - if not help_property: - new_prop = prop.execute(option_bag, - for_settings=True, - ) - else: - new_prop = prop.help(option_bag, - for_settings=True, - ) - if isinstance(new_prop, str): - new_prop = (new_prop, new_prop) - if new_prop is None: + try: + if not help_property: + new_prop = prop.execute(option_bag, + for_settings=True, + ) + else: + new_prop = prop.help(option_bag, + for_settings=True, + ) + if isinstance(new_prop, str): + new_prop = (new_prop, new_prop) + if new_prop is None: + continue + except ConfigError as err: + if transitive_raise: + raise err from err continue if (not help_property and not isinstance(new_prop, str)) or \ (help_property and not isinstance(new_prop, tuple)): @@ -514,7 +523,7 @@ class Settings: props -= self.getpermissives(option_bag) if not uncalculated and apply_requires and \ not option_bag.config_bag.is_unrestraint and \ - not help_property: + not help_property and transitive_raise: cache.setcache(option_bag, props, type_='properties', @@ -683,15 +692,17 @@ class Settings: option_bag, apply_requires=True, uncalculated=False, + transitive_raise=True, ): """raise if needed """ - if not uncalculated and apply_requires: + if not uncalculated and apply_requires and option_bag.properties is not None: option_properties = option_bag.properties else: option_properties = self.getproperties(option_bag, apply_requires=apply_requires, uncalculated=uncalculated, + transitive_raise=transitive_raise, ) return self._calc_raises_properties(option_bag.config_bag.properties, option_bag.config_bag.permissives, @@ -721,26 +732,30 @@ class Settings: if not config_properties or config_properties == frozenset(['cache']): # if no global property return - properties = self.calc_raises_properties(option_bag) - if properties != frozenset(): - if need_help: - help_properties = dict(self.getproperties(option_bag, - help_property=True, - )) - calc_properties = [] - for property_ in self._calc_raises_properties(option_bag.config_bag.properties, - option_bag.config_bag.permissives, - set(help_properties.keys()), - ): - calc_properties.append(help_properties[property_]) - calc_properties = frozenset(calc_properties) - else: - calc_properties = properties - raise PropertiesOptionError(option_bag, - properties, - self, - help_properties=calc_properties, - ) + for transitive_raise in [False, True]: + properties = self.calc_raises_properties(option_bag, + transitive_raise=transitive_raise, + ) + if properties != frozenset(): + if need_help: + help_properties = dict(self.getproperties(option_bag, + help_property=True, + transitive_raise=transitive_raise, + )) + calc_properties = [] + for property_ in self._calc_raises_properties(option_bag.config_bag.properties, + option_bag.config_bag.permissives, + set(help_properties.keys()), + ): + calc_properties.append(help_properties[property_]) + calc_properties = frozenset(calc_properties) + else: + calc_properties = properties + raise PropertiesOptionError(option_bag, + properties, + self, + help_properties=calc_properties, + ) def validate_mandatory(self, value,