diff --git a/test/test_freeze.py b/test/test_freeze.py index 277768e..4240f07 100644 --- a/test/test_freeze.py +++ b/test/test_freeze.py @@ -21,10 +21,10 @@ def make_description_freeze(): stroption = StrOption('str', 'Test string option', default="abc") boolop = BoolOption('boolop', 'Test boolean option op', default=[True], multi=True) wantref_option = BoolOption('wantref', 'Test requires', default=False, properties=('force_store_value',), - requires=((booloption, True, 'hidden'),)) + requires=({'option': booloption, 'expected': True, 'action': 'hidden'},)) wantframework_option = BoolOption('wantframework', 'Test requires', default=False, - requires=((booloption, True, 'hidden'),)) + requires=({'option': booloption, 'expected': True, 'action': 'hidden'},)) gcgroup = OptionDescription('gc', '', [gcoption, gcdummy, floatoption]) descr = OptionDescription('tiramisu', '', [gcgroup, booloption, objspaceoption, diff --git a/test/test_option_calculation.py b/test/test_option_calculation.py index 2230fba..4dc37e8 100644 --- a/test/test_option_calculation.py +++ b/test/test_option_calculation.py @@ -32,10 +32,10 @@ def make_description(): stroption = StrOption('str', 'Test string option', default="abc") boolop = BoolOption('boolop', 'Test boolean option op', default=True) wantref_option = BoolOption('wantref', 'Test requires', default=False, - requires=((boolop, True, 'hidden'),)) + requires=({'option': boolop, 'expected': True, 'action': 'hidden'},)) wantframework_option = BoolOption('wantframework', 'Test requires', default=False, - requires=((boolop, True, 'hidden'),)) + requires=({'option': boolop, 'expected': True, 'action': 'hidden'},)) gcgroup = OptionDescription('gc', '', [gcoption, gcdummy, floatoption, intoption2]) descr = OptionDescription('constraints', '', [gcgroup, booloption, objspaceoption, wantref_option, stroption, @@ -56,10 +56,10 @@ def make_description_duplicates(): stroption = StrOption('str', 'Test string option', default="abc") boolop = BoolOption('boolop', 'Test boolean option op', default=True) wantref_option = BoolOption('wantref', 'Test requires', default=False, - requires=((boolop, True, 'hidden'),)) + requires=({'option': boolop, 'expected': True, 'action': 'hidden'},)) wantframework_option = BoolOption('wantframework', 'Test requires', default=False, - requires=((boolop, True, 'hidden'),)) + requires=({'option': boolop, 'expected': True, 'action': 'hidden'},)) # dummy2 (same path) gcdummy2 = BoolOption('dummy', 'dummy2', default=True) # dummy3 (same name) @@ -94,11 +94,11 @@ def make_description2(): boolop = BoolOption('boolop', 'Test boolean option op', default=True) boolop.enable_multi() wantref_option = BoolOption('wantref', 'Test requires', default=False, - requires=((boolop, True, 'hidden'),)) + requires=({'option': boolop, 'expected': True, 'action': 'hidden'},)) # second multi wantframework_option = BoolOption('wantframework', 'Test requires', default=False, - requires=((boolop, True, 'hidden'),)) + requires=({'option': boolop, 'expected': True, 'action': 'hidden'},)) wantframework_option.enable_multi() gcgroup = OptionDescription('gc', '', [gcoption, gcdummy, floatoption]) @@ -167,7 +167,7 @@ def make_description_requires(): booloption = BoolOption('bool', 'Test boolean option', default=True) intoption = IntOption('int', 'Test int option', default=0) stroption = StrOption('str', 'Test string option', default="abc", - requires=((intoption, 1, 'hidden'),)) + requires=({'option': intoption, 'expected': 1, 'action': 'hidden'},)) gcgroup = OptionDescription('gc', '', [gcoption, gcdummy, floatoption]) descr = OptionDescription('constraints', '', [gcgroup, booloption, objspaceoption, @@ -200,7 +200,7 @@ def test_hidden_if_in_with_group(): intoption = IntOption('int', 'Test int option', default=0) stroption = StrOption('str', 'Test string option', default="abc") gcgroup = OptionDescription('gc', '', [gcoption, gcdummy, floatoption], - requires=((intoption, 1, 'hidden'),)) + requires=({'option': intoption, 'expected': 1, 'action': 'hidden'},)) descr = OptionDescription('constraints', '', [gcgroup, booloption, objspaceoption, stroption, intoption]) cfg = Config(descr) @@ -223,7 +223,7 @@ def test_disabled_with_group(): intoption = IntOption('int', 'Test int option', default=0) stroption = StrOption('str', 'Test string option', default="abc") gcgroup = OptionDescription('gc', '', [gcoption, gcdummy, floatoption], - requires=((intoption, 1, 'disabled'),)) + requires=({'option': intoption, 'expected': 1, 'action': 'disabled'},)) descr = OptionDescription('constraints', '', [gcgroup, booloption, objspaceoption, stroption, intoption]) cfg = Config(descr) @@ -245,10 +245,10 @@ def make_description_callback(): stroption = StrOption('str', 'Test string option', default="abc") boolop = BoolOption('boolop', 'Test boolean option op', default=True) wantref_option = BoolOption('wantref', 'Test requires', default=False, - requires=((boolop, True, 'hidden'),)) + requires=({'option': boolop, 'expected': True, 'action': 'hidden'},)) wantframework_option = BoolOption('wantframework', 'Test requires', default=False, - requires=((boolop, True, 'hidden'),)) + requires=({'option': boolop, 'expected': True, 'action': 'hidden'},)) gcgroup = OptionDescription('gc', '', [gcoption, gcdummy, floatoption]) descr = OptionDescription('constraints', '', [gcgroup, booloption, objspaceoption, wantref_option, stroption, diff --git a/test/test_option_setting.py b/test/test_option_setting.py index 15c8925..f77fa8e 100644 --- a/test/test_option_setting.py +++ b/test/test_option_setting.py @@ -131,7 +131,7 @@ def test_multi_with_requires(): s = StrOption("string", "", default=["string"], default_multi="string", multi=True) intoption = IntOption('int', 'Test int option', default=0) stroption = StrOption('str', 'Test string option', default=["abc"], default_multi="abc", - requires=[(intoption, 1, 'hidden')], multi=True) + requires=[{'option': intoption, 'expected': 1, 'action': 'hidden'}], multi=True) descr = OptionDescription("options", "", [s, intoption, stroption]) config = Config(descr) setting = config.cfgimpl_get_settings() @@ -146,7 +146,7 @@ def test__requires_with_inverted(): s = StrOption("string", "", default=["string"], multi=True) intoption = IntOption('int', 'Test int option', default=0) stroption = StrOption('str', 'Test string option', default=["abc"], default_multi="abc", - requires=[(intoption, 1, 'hide', 'inverted')], multi=True) + requires=[{'option': intoption, 'expected': 1, 'action': 'hide', 'inverse': True}], multi=True) descr = OptionDescription("options", "", [s, intoption, stroption]) config = Config(descr) setting = config.cfgimpl_get_settings() @@ -160,7 +160,7 @@ def test_multi_with_requires_in_another_group(): intoption = IntOption('int', 'Test int option', default=0) descr = OptionDescription("options", "", [intoption]) stroption = StrOption('str', 'Test string option', default=["abc"], - requires=[(intoption, 1, 'hidden')], multi=True) + requires=[{'option': intoption, 'expected': 1, 'action': 'hidden'}], multi=True) descr = OptionDescription("opt", "", [stroption]) descr2 = OptionDescription("opt2", "", [intoption, s, descr]) config = Config(descr2) @@ -177,7 +177,7 @@ def test_apply_requires_from_config(): intoption = IntOption('int', 'Test int option', default=0) descr = OptionDescription("options", "", [intoption]) stroption = StrOption('str', 'Test string option', default=["abc"], - requires=[(intoption, 1, 'hidden')], multi=True) + requires=[{'option': intoption, 'expected': 1, 'action': 'hidden'}], multi=True) descr = OptionDescription("opt", "", [stroption]) descr2 = OptionDescription("opt2", "", [intoption, s, descr]) config = Config(descr2) @@ -194,7 +194,7 @@ def test_apply_requires_with_disabled(): intoption = IntOption('int', 'Test int option', default=0) descr = OptionDescription("options", "", [intoption]) stroption = StrOption('str', 'Test string option', default=["abc"], - requires=[(intoption, 1, 'disabled')], multi=True) + requires=[{'option': intoption, 'expected': 1, 'action': 'disabled'}], multi=True) descr = OptionDescription("opt", "", [stroption]) descr2 = OptionDescription("opt2", "", [intoption, s, descr]) config = Config(descr2) @@ -211,7 +211,7 @@ def test_multi_with_requires_with_disabled_in_another_group(): intoption = IntOption('int', 'Test int option', default=0) descr = OptionDescription("options", "", [intoption]) stroption = StrOption('str', 'Test string option', default=["abc"], - requires=[(intoption, 1, 'disabled')], multi=True) + requires=[{'option': intoption, 'expected': 1, 'action': 'disabled'}], multi=True) descr = OptionDescription("opt", "", [stroption]) descr2 = OptionDescription("opt2", "", [intoption, s, descr]) config = Config(descr2) @@ -226,7 +226,7 @@ def test_multi_with_requires_with_disabled_in_another_group(): def test_multi_with_requires_that_is_multi(): s = StrOption("string", "", default=["string"], multi=True) intoption = IntOption('int', 'Test int option', default=[0], multi=True) - raises(ValueError, "StrOption('str', 'Test string option', default=['abc'], requires=[(intoption, 1, 'hidden')], multi=True)") + raises(ValueError, "StrOption('str', 'Test string option', default=['abc'], requires=[{'option': intoption, 'expected': 1, 'action': 'hidden'}], multi=True)") def test_multi_with_bool(): diff --git a/test/test_option_type.py b/test/test_option_type.py index e4a3656..071563f 100644 --- a/test/test_option_type.py +++ b/test/test_option_type.py @@ -20,10 +20,10 @@ def make_description(): stroption = StrOption('str', 'Test string option', default="abc") wantref_option = BoolOption('wantref', 'Test requires', default=False, - requires=((gcoption, 'ref', 'hidden'),)) + requires=({'option': gcoption, 'expected': 'ref', 'action': 'hidden'},)) wantframework_option = BoolOption('wantframework', 'Test requires', default=False, - requires=((gcoption, 'framework', 'hidden'),)) + requires=({'option': gcoption, 'expected': 'framework', 'action': 'hidden'},)) # ____________________________________________________________ booloptiontwo = BoolOption('booltwo', 'Test boolean option two', default=False) diff --git a/test/test_requires.py b/test/test_requires.py index 309a3fd..61dfdee 100644 --- a/test/test_requires.py +++ b/test/test_requires.py @@ -1,5 +1,6 @@ # coding: utf-8 import autopath +from copy import copy from tiramisu import setting setting.expires_time = 1 from tiramisu.option import IPOption, OptionDescription, BoolOption, IntOption @@ -11,7 +12,7 @@ from py.test import raises def test_requires(): a = BoolOption('activate_service', '', True) b = IPOption('ip_address_service', '', - requires=[(a, False, 'disabled')]) + requires=[{'option': a, 'expected': False, 'action': 'disabled'}]) od = OptionDescription('service', '', [a, b]) c = Config(od) c.read_write() @@ -28,10 +29,12 @@ def test_requires(): def test_requires_same_action(): a = BoolOption('activate_service', '', True) b = BoolOption('activate_service_web', '', True, - requires=[(a, False, 'new')]) + requires=[{'option': a, 'expected': False, 'action': 'new'}]) d = IPOption('ip_address_service_web', '', - requires=[(b, False, 'disabled', False, True, False)]) + requires=[{'option': b, 'expected': False, + 'action': 'disabled', 'inverse': False, + 'transitive': True, 'same_action': False}]) od = OptionDescription('service', '', [a, b, d]) c = Config(od) c.read_write() @@ -59,10 +62,10 @@ def test_requires_same_action(): def test_requires_transitive(): a = BoolOption('activate_service', '', True) b = BoolOption('activate_service_web', '', True, - requires=[(a, False, 'disabled')]) + requires=[{'option': a, 'expected': False, 'action': 'disabled'}]) d = IPOption('ip_address_service_web', '', - requires=[(b, False, 'disabled')]) + requires=[{'option': b, 'expected': False, 'action': 'disabled'}]) od = OptionDescription('service', '', [a, b, d]) c = Config(od) c.read_write() @@ -90,10 +93,10 @@ def test_requires_transitive_bis(): a = BoolOption('activate_service', '', True) abis = BoolOption('activate_service_bis', '', True) b = BoolOption('activate_service_web', '', True, - requires=[(a, True, 'disabled', True)]) + requires=[{'option': a, 'expected': True, 'action': 'disabled', 'inverse': True}]) d = IPOption('ip_address_service_web', '', - requires=[(b, True, 'disabled', True)]) + requires=[{'option': b, 'expected': True, 'action': 'disabled', 'inverse': True}]) od = OptionDescription('service', '', [a, abis, b, d]) c = Config(od) c.read_write() @@ -120,9 +123,9 @@ def test_requires_transitive_bis(): def test_requires_transitive_hidden_disabled(): a = BoolOption('activate_service', '', True) b = BoolOption('activate_service_web', '', True, - requires=[(a, False, 'hidden')]) + requires=[{'option': a, 'expected': False, 'action': 'hidden'}]) d = IPOption('ip_address_service_web', '', - requires=[(b, False, 'disabled')]) + requires=[{'option': b, 'expected': False, 'action': 'disabled'}]) od = OptionDescription('service', '', [a, b, d]) c = Config(od) c.read_write() @@ -143,9 +146,10 @@ def test_requires_transitive_hidden_disabled(): def test_requires_not_transitive(): a = BoolOption('activate_service', '', True) b = BoolOption('activate_service_web', '', True, - requires=[(a, False, 'disabled')]) + requires=[{'option': a, 'expected': False, 'action': 'disabled'}]) d = IPOption('ip_address_service_web', '', - requires=[(b, False, 'disabled', False, False)]) + requires=[{'option': b, 'expected': False, + 'action': 'disabled', 'transitive': False}]) od = OptionDescription('service', '', [a, b, d]) c = Config(od) c.read_write() @@ -167,7 +171,7 @@ def test_requires_not_transitive(): def test_requires_None(): a = BoolOption('activate_service', '') b = IPOption('ip_address_service', '', - requires=[(a, None, 'disabled')]) + requires=[{'option': a, 'expected': None, 'action': 'disabled'}]) od = OptionDescription('service', '', [a, b]) c = Config(od) c.read_write() @@ -185,7 +189,8 @@ def test_requires_multi_disabled(): a = BoolOption('activate_service', '') b = IntOption('num_service', '') c = IPOption('ip_address_service', '', - requires=[(a, True, 'disabled'), (b, 1, 'disabled')]) + requires=[{'option': a, 'expected': True, 'action': 'disabled'}, + {'option': b, 'expected': 1, 'action': 'disabled'}]) od = OptionDescription('service', '', [a, b, c]) c = Config(od) c.read_write() @@ -219,11 +224,15 @@ def test_requires_multi_disabled(): props = err.proptype assert props == ['disabled'] + def test_requires_multi_disabled_inverse(): a = BoolOption('activate_service', '') b = IntOption('num_service', '') c = IPOption('ip_address_service', '', - requires=[(a, True, 'disabled', True), (b, 1, 'disabled', True)]) + requires=[{'option': a, 'expected': True, + 'action': 'disabled', 'inverse': True}, + {'option': b, 'expected': 1, + 'action': 'disabled', 'inverse': True}]) od = OptionDescription('service', '', [a, b, c]) c = Config(od) c.read_write() @@ -261,3 +270,103 @@ def test_requires_multi_disabled_inverse(): c.activate_service = True c.ip_address_service + + +def test_requires_multi_disabled_2(): + a = BoolOption('a', '') + b = BoolOption('b', '') + c = BoolOption('c', '') + d = BoolOption('d', '') + e = BoolOption('e', '') + f = BoolOption('f', '') + g = BoolOption('g', '') + h = BoolOption('h', '') + i = BoolOption('i', '') + j = BoolOption('j', '') + k = BoolOption('k', '') + l = BoolOption('l', '') + m = BoolOption('m', '') + list_bools = [a, b, c, d, e, f, g, h, i, j, k, l, m] + requires = [] + for boo in list_bools: + requires.append({'option': boo, 'expected': True, 'action': 'disabled'}) + z = IPOption('z', '', requires=requires) + y = copy(list_bools) + y.append(z) + od = OptionDescription('service', '', y) + cfg = Config(od) + cfg.read_write() + + cfg.z + for boo in list_bools: + setattr(cfg, boo._name, True) + props = [] + try: + cfg.z + except PropertiesOptionError, err: + props = err.proptype + assert props == ['disabled'] + for boo in list_bools: + setattr(cfg, boo._name, False) + if boo == m: + cfg.z + else: + props = [] + try: + cfg.z + except PropertiesOptionError, err: + props = err.proptype + assert props == ['disabled'] + + +def test_requires_multi_disabled_inverse_2(): + a = BoolOption('a', '') + b = BoolOption('b', '') + c = BoolOption('c', '') + d = BoolOption('d', '') + e = BoolOption('e', '') + f = BoolOption('f', '') + g = BoolOption('g', '') + h = BoolOption('h', '') + i = BoolOption('i', '') + j = BoolOption('j', '') + k = BoolOption('k', '') + l = BoolOption('l', '') + m = BoolOption('m', '') + list_bools = [a, b, c, d, e, f, g, h, i, j, k, l, m] + requires = [] + for boo in list_bools: + requires.append({'option': boo, 'expected': True, 'action': 'disabled', + 'inverse': True}) + z = IPOption('z', '', requires=requires) + y = copy(list_bools) + y.append(z) + od = OptionDescription('service', '', y) + cfg = Config(od) + cfg.read_write() + + props = [] + try: + cfg.z + except PropertiesOptionError, err: + props = err.proptype + assert props == ['disabled'] + for boo in list_bools: + setattr(cfg, boo._name, True) + if boo == m: + cfg.z + else: + props = [] + try: + cfg.z + except PropertiesOptionError, err: + props = err.proptype + assert props == ['disabled'] + for boo in list_bools: + setattr(cfg, boo._name, False) + props = [] + try: + cfg.z + except PropertiesOptionError, err: + props = err.proptype + assert props == ['disabled'] diff --git a/test/test_symlink.py b/test/test_symlink.py index e858a53..1acdbb8 100644 --- a/test/test_symlink.py +++ b/test/test_symlink.py @@ -30,7 +30,9 @@ def test_symlink_option(): def test_symlink_requires(): boolopt = BoolOption('b', '', default=True) - stropt = StrOption('s', '', requires=[(boolopt, False, 'disabled')]) + stropt = StrOption('s', '', requires=[{'option': boolopt, + 'expected': False, + 'action': 'disabled'}]) linkopt = SymLinkOption("c", stropt) descr = OptionDescription('opt', '', [boolopt, stropt, linkopt]) config = Config(descr) diff --git a/tiramisu/option.py b/tiramisu/option.py index 361919c..50ba42a 100644 --- a/tiramisu/option.py +++ b/tiramisu/option.py @@ -125,7 +125,7 @@ class Option(BaseInformation): self._name = name self._impl_informations = {} self.impl_set_information('doc', doc) - validate_requires_arg(requires, self._name) + requires = validate_requires_arg(requires, self._name) self._requires = requires self._multi = multi self._consistencies = None @@ -645,7 +645,7 @@ class OptionDescription(BaseInformation): '{0}').format(child)) old = child self._children = (tuple(child_names), tuple(children)) - validate_requires_arg(requires, self._name) + requires = validate_requires_arg(requires, self._name) self._requires = requires self._cache_paths = None self._consistencies = None @@ -812,35 +812,63 @@ class OptionDescription(BaseInformation): def validate_requires_arg(requires, name): - "check malformed requirements" - if requires is not None: - config_action = {} - for req in requires: - if not type(req) == tuple: - raise ValueError(_("malformed requirements type for option:" - " {0}, must be a tuple").format(name)) - if not isinstance(req[0], Option): - raise ValueError(_('malformed requirements first argument ' - 'must be an option in option {0}').format(name)) - if req[0].impl_is_multi(): - raise ValueError(_('malformed requirements option {0} ' - 'should not be a multi').format(name)) - if req[1] is not None and not req[0]._validate(req[1]): - raise ValueError(_('malformed requirements second argument ' - 'must be valid for option {0}').format(name)) - if len(req) == 3: - action = req[2] - inverse = False - elif len(req) in [4, 5, 6]: - action = req[2] - inverse = req[3] - else: - raise ValueError(_("malformed requirements for option: {0}" - " invalid len").format(name)) - if action in config_action: - if inverse != config_action[action]: - raise ValueError(_("inconsistency in action types for option: {0}" - " action: {1}").format(name, action)) - else: - config_action[action] = inverse - return requires + """check malformed requirements + and tranform dict to tuple""" + if requires is None: + return None + ret_requires = [] + config_action = {} + for require in requires: + if not type(require) == dict: + raise ValueError(_("malformed requirements type for option:" + " {0}, must be a dict").format(name)) + valid_keys = ('option', 'expected', 'action', 'inverse', 'transitive', + 'same_action') + unknown_keys = frozenset(require.keys()) - frozenset(valid_keys) + if unknown_keys != frozenset(): + raise ValueError('malformed requirements for option: {0}' + ' unknown keys {1}, must only ' + '{2}'.format(name, + unknown_keys, + valid_keys)) + try: + option = require['option'] + expected = require['expected'] + action = require['action'] + except KeyError: + raise ValueError(_("malformed requirements for option: {0}" + " require must have option, expected and" + " action keys").format(name)) + inverse = require.get('inverse', False) + if inverse not in [True, False]: + raise ValueError(_('malformed requirements for option: {0}' + ' inverse must be boolean')) + transitive = require.get('transitive', True) + if transitive not in [True, False]: + raise ValueError(_('malformed requirements for option: {0}' + ' transitive must be boolean')) + same_action = require.get('same_action', True) + if same_action not in [True, False]: + raise ValueError(_('malformed requirements for option: {0}' + ' same_action must be boolean')) + + if not isinstance(option, Option): + raise ValueError(_('malformed requirements first argument ' + 'must be an option in option {0}').format(name)) + if option.impl_is_multi(): + raise ValueError(_('malformed requirements option {0} ' + 'should not be a multi').format(name)) + if expected is not None and not option._validate(expected): + raise ValueError(_('malformed requirements second argument ' + 'must be valid for option {0}').format(name)) + if action in config_action: + if inverse != config_action[action]: + raise ValueError(_("inconsistency in action types for option: {0}" + " action: {1}").format(name, action)) + else: + config_action[action] = inverse + + ret_requires.append((option, expected, action, inverse, transitive, + same_action)) + + return tuple(ret_requires) diff --git a/tiramisu/setting.py b/tiramisu/setting.py index 4604a60..a109006 100644 --- a/tiramisu/setting.py +++ b/tiramisu/setting.py @@ -334,6 +334,9 @@ class Setting(object): def apply_requires(opt, config): "carries out the jit (just in time requirements between options" + if opt._requires is None: + return + def build_actions(requires): "action are hide, show, enable, disable..." trigger_actions = {} @@ -341,74 +344,42 @@ def apply_requires(opt, config): action = require[2] trigger_actions.setdefault(action, []).append(require) return trigger_actions - #for symlink - if hasattr(opt, '_requires') and opt._requires is not None: - # filters the callbacks - settings = config.cfgimpl_get_settings() - setting = Property(settings, settings._get_properties(opt, False), opt) - trigger_actions = build_actions(opt._requires) - descr = config.cfgimpl_get_context().cfgimpl_get_description() - optpath = descr.impl_get_path_by_opt(opt) - for requires in trigger_actions.values(): - matches = False - for require in requires: - if len(require) == 3: - option, expected, action = require - inverse = False - transitive = True - same_action = True - elif len(require) == 4: - option, expected, action, inverse = require - transitive = True - same_action = True - elif len(require) == 5: - option, expected, action, inverse, transitive = require - same_action = True - elif len(require) == 6: - option, expected, action, inverse, transitive, same_action = require - path = descr.impl_get_path_by_opt(option) - if path == optpath or path.startswith(optpath + '.'): - raise RequirementError(_("malformed requirements " - "imbrication detected for option: '{0}' " - "with requirement on: '{1}'").format(optpath, path)) - try: - value = config.cfgimpl_get_context()._getattr(path, force_permissive=True) - except PropertiesOptionError, err: - if not transitive: - continue - properties = err.proptype - if same_action and action not in properties: - raise RequirementError(_("option '{0}' has requirement's property error: " - "{1} {2}").format(opt._name, path, properties)) - #transitive action, force expected - value = expected - inverse = False - except AttributeError: - raise AttributeError(_("required option not found: " - "{0}").format(path)) - if value == expected: - matches = True - if inverse: - #temporary remove, definitive if no value != expected - #matches - setting.remove(action) - else: - setting.append(action) - ## the calculation cannot be carried out - break - if value != expected: - matches = True - if inverse: - setting.append(action) - # the calculation cannot be carried out - break - else: - #temporary remove, definitive if no value != expected - #matches - setting.remove(action) - # no requirement has been triggered, then just reverse the action - if not matches: - if inverse: - setting.append(action) - else: - setting.remove(action) + + # filters the callbacks + settings = config.cfgimpl_get_settings() + setting = Property(settings, settings._get_properties(opt, False), opt) + trigger_actions = build_actions(opt._requires) + descr = config.cfgimpl_get_context().cfgimpl_get_description() + optpath = descr.impl_get_path_by_opt(opt) + for requires in trigger_actions.values(): + matches = False + for require in requires: + option, expected, action, inverse, transitive, same_action = require + path = descr.impl_get_path_by_opt(option) + if path == optpath or path.startswith(optpath + '.'): + raise RequirementError(_("malformed requirements " + "imbrication detected for option: '{0}' " + "with requirement on: '{1}'").format(optpath, path)) + try: + value = config.cfgimpl_get_context()._getattr(path, force_permissive=True) + except PropertiesOptionError, err: + if not transitive: + continue + properties = err.proptype + if same_action and action not in properties: + raise RequirementError(_("option '{0}' has requirement's property error: " + "{1} {2}").format(opt._name, path, properties)) + #transitive action, force expected + value = expected + inverse = False + except AttributeError: + raise AttributeError(_("required option not found: " + "{0}").format(path)) + if not inverse and value == expected or inverse and value != expected: + matches = True + setting.append(action) + ## the calculation cannot be carried out + break + # no requirement has been triggered, then just reverse the action + if not matches: + setting.remove(action)