From 52ddd76b1a38cc7ef483a7c39c2c397982b4be31 Mon Sep 17 00:00:00 2001 From: Emmanuel Garette Date: Wed, 25 Dec 2019 20:44:56 +0100 Subject: [PATCH] corrections in dict and todict --- tests/dict/data/choice1_requires.py | 10 +- .../data/unicode1_leadership_requires.json | 5 +- .../dict/data/unicode1_leadership_requires.py | 15 +- .../unicode1_leadership_requires_all.json | 4 +- .../data/unicode1_leadership_requires_all.py | 13 +- ...1_leadership_requires_disabled_value.json} | 79 +++++--- ...ode1_leadership_requires_disabled_value.py | 33 ++++ ...unicode1_leadership_requires_follower.json | 5 +- .../unicode1_leadership_requires_follower.py | 14 +- ...e1_leadership_requires_follower_value.json | 7 +- ...ode1_leadership_requires_follower_value.py | 16 +- ...nicode1_leadership_requires_followers.json | 5 +- .../unicode1_leadership_requires_followers.py | 14 +- .../unicode1_leadership_requires_leader.py | 19 -- .../unicode1_leadership_requires_value.json | 5 +- .../unicode1_leadership_requires_value.py | 14 +- tests/dict/data/unicode1_multi_requires.json | 7 +- tests/dict/data/unicode1_multi_requires.py | 13 +- .../unicode1_optiondescription_requires.json | 1 - .../unicode1_optiondescription_requires.py | 13 +- tests/dict/data/unicode1_requires.py | 12 +- tests/dict/test_json.py | 2 +- tests/test_cache.py | 6 +- tests/test_config_api.py | 23 +-- tests/test_dyn_optiondescription.py | 91 +++++++++- tests/test_leadership.py | 22 +-- tests/test_requires.py | 10 +- tests/test_slots.py | 1 - tiramisu/api.py | 32 ++-- tiramisu/autolib.py | 10 +- tiramisu/config.py | 168 +++++++----------- tiramisu/option/dynoptiondescription.py | 1 - tiramisu/option/leadership.py | 12 +- tiramisu/option/option.py | 2 - tiramisu/option/optiondescription.py | 5 +- tiramisu/option/syndynoptiondescription.py | 13 ++ tiramisu/setting.py | 16 +- tiramisu/todict.py | 9 +- tiramisu/value.py | 7 +- 39 files changed, 402 insertions(+), 332 deletions(-) rename tests/dict/data/{unicode1_leadership_requires_leader.json => unicode1_leadership_requires_disabled_value.json} (51%) create mode 100644 tests/dict/data/unicode1_leadership_requires_disabled_value.py delete mode 100644 tests/dict/data/unicode1_leadership_requires_leader.py diff --git a/tests/dict/data/choice1_requires.py b/tests/dict/data/choice1_requires.py index 101a1ba..b62bb20 100644 --- a/tests/dict/data/choice1_requires.py +++ b/tests/dict/data/choice1_requires.py @@ -1,12 +1,14 @@ -from tiramisu.option import ChoiceOption, StrOption, OptionDescription +from tiramisu import ChoiceOption, StrOption, OptionDescription, Calculation, ParamValue, ParamOption, Params, calc_value def get_description(): """generate description for this test """ option1 = ChoiceOption('choice', "Choice description", ("hide", "show"), default='hide', properties=('mandatory',)) - option2 = StrOption('unicode2', "Unicode 2", requires=[{'option': option1, - 'expected': 'hide', - 'action': 'hidden'}]) + hidden_property = Calculation(calc_value, + Params(ParamValue('hidden'), + kwargs={'condition': ParamOption(option1, todict=True), + 'expected': ParamValue('hide')})) + option2 = StrOption('unicode2', "Unicode 2", properties=(hidden_property,)) descr1 = OptionDescription("options", "Common configuration", [option1, option2]) descr = OptionDescription("choice1_requires", "Choice with requirement", [descr1]) return descr diff --git a/tests/dict/data/unicode1_leadership_requires.json b/tests/dict/data/unicode1_leadership_requires.json index 78380d5..6f7062b 100644 --- a/tests/dict/data/unicode1_leadership_requires.json +++ b/tests/dict/data/unicode1_leadership_requires.json @@ -35,7 +35,10 @@ }, "model": { "options.unicode.unicode": { - "required": true + "required": true, + "properties": [ + "unique" + ] } }, "global": { diff --git a/tests/dict/data/unicode1_leadership_requires.py b/tests/dict/data/unicode1_leadership_requires.py index 6c910dd..b2545d7 100644 --- a/tests/dict/data/unicode1_leadership_requires.py +++ b/tests/dict/data/unicode1_leadership_requires.py @@ -1,6 +1,4 @@ -from tiramisu.option import StrOption, OptionDescription -from tiramisu import Leadership - +from tiramisu import StrOption, OptionDescription, Leadership, Calculation, ParamValue, ParamOption, Params, calc_value def get_description(): """generate description for this test @@ -8,11 +6,12 @@ def get_description(): option = StrOption('unicode', "Unicode leader", multi=True) option1 = StrOption('unicode1', "Unicode follower 1", multi=True) option2 = StrOption('unicode2', "Values 'test' must show 'Unicode follower 3'", multi=True) - option3 = StrOption('unicode3', "Unicode follower 3", requires=[{'option': option2, - 'expected': u'test', - 'action': 'hidden', - 'inverse': True}], - multi=True) + hidden_property = Calculation(calc_value, + Params(ParamValue('hidden'), + kwargs={'condition': ParamOption(option2, todict=True), + 'expected': ParamValue('test'), + 'reverse_condition': ParamValue(True)})) + option3 = StrOption('unicode3', "Unicode follower 3", properties=(hidden_property,), multi=True) descr1 = Leadership("unicode", "Common configuration 1", [option, option1, option2, option3]) descr = OptionDescription("options", "Common configuration 2", [descr1]) diff --git a/tests/dict/data/unicode1_leadership_requires_all.json b/tests/dict/data/unicode1_leadership_requires_all.json index fb14b9e..cdf127d 100644 --- a/tests/dict/data/unicode1_leadership_requires_all.json +++ b/tests/dict/data/unicode1_leadership_requires_all.json @@ -34,13 +34,15 @@ }, "model": { "options.unicode1": { - "display": false, "properties": [ "hidden" ] }, "options.unicode1.unicode1": { "required": true, + "properties": [ + "unique" + ], "hidden": true, "display": false } diff --git a/tests/dict/data/unicode1_leadership_requires_all.py b/tests/dict/data/unicode1_leadership_requires_all.py index 2958782..f9164f8 100644 --- a/tests/dict/data/unicode1_leadership_requires_all.py +++ b/tests/dict/data/unicode1_leadership_requires_all.py @@ -1,5 +1,4 @@ -from tiramisu.option import StrOption, OptionDescription -from tiramisu import Leadership +from tiramisu import StrOption, OptionDescription, Leadership, Calculation, ParamValue, ParamOption, Params, calc_value def get_description(): @@ -9,11 +8,13 @@ def get_description(): option1 = StrOption('unicode1', "Unicode leader", multi=True) option2 = StrOption('unicode2', "Unicode follower 1", multi=True) option3 = StrOption('unicode3', "Unicode follower 2", multi=True) + hidden_property = Calculation(calc_value, + Params(ParamValue('hidden'), + kwargs={'condition': ParamOption(option, todict=True), + 'expected': ParamValue('test'), + 'reverse_condition': ParamValue(True)})) descr1 = Leadership("unicode1", "Common configuration", - [option1, option2, option3], requires=[{'option': option, - 'expected': u'test', - 'action': 'hidden', - 'inverse': True}]) + [option1, option2, option3], properties=(hidden_property,)) descr = OptionDescription("options", "Common configuration", [option, descr1]) descr = OptionDescription("unicode1_leadership_requires_all", "Leader follower with requirement", [descr]) return descr diff --git a/tests/dict/data/unicode1_leadership_requires_leader.json b/tests/dict/data/unicode1_leadership_requires_disabled_value.json similarity index 51% rename from tests/dict/data/unicode1_leadership_requires_leader.json rename to tests/dict/data/unicode1_leadership_requires_disabled_value.json index b3c3f11..c5c2974 100644 --- a/tests/dict/data/unicode1_leadership_requires_leader.json +++ b/tests/dict/data/unicode1_leadership_requires_disabled_value.json @@ -3,46 +3,75 @@ "options": { "properties": { "options.unicode": { - "type": "string", - "title": "Value 'test' must show leader" - }, - "options.unicode1": { "properties": { - "options.unicode1.unicode1": { + "options.unicode.unicode": { "type": "string", "isMulti": true, - "title": "Unicode leader" + "title": "Values 'test' must show 'Unicode follower 3'" }, - "options.unicode1.unicode2": { + "options.unicode.unicode1": { "type": "string", "isMulti": true, "title": "Unicode follower 1" }, - "options.unicode1.unicode3": { + "options.unicode.unicode2": { "type": "string", "isMulti": true, "title": "Unicode follower 2" + }, + "options.unicode.unicode3": { + "type": "string", + "isMulti": true, + "title": "Unicode follower 3" } }, "type": "array", - "title": "Common configuration" + "title": "Common configuration 1" } }, "type": "object", - "title": "Common configuration" + "title": "Common configuration 2" } }, "model": { - "options.unicode1": { - "display": false, - "properties": [ - "hidden" - ] - }, - "options.unicode1.unicode1": { + "options.unicode.unicode": { "required": true, - "hidden": true, - "display": false + "properties": [ + "unique" + ], + "value": [ + "test", + "val2" + ], + "owner": "user" + }, + "options.unicode.unicode1": { + "0": { + "value": "super1", + "owner": "user" + }, + "1": { + "value": "super2", + "owner": "user" + } + }, + "options.unicode.unicode2": { + "0": { + "value": "pas test", + "owner": "user" + }, + "1": { + "value": "test", + "owner": "user" + } + }, + "options.unicode.unicode3": { + "1": { + "hidden": true, + "display": false, + "value": "super", + "owner": "user" + } } }, "global": { @@ -62,33 +91,33 @@ ] }, "form": { - "options.unicode": { + "options.unicode.unicode": { "clearable": true, "type": "input", "dependencies": { "default": { "hide": [ - "options.unicode1" + "options.unicode.unicode3" ] }, "expected": { "test": { "show": [ - "options.unicode1" + "options.unicode.unicode3" ] } } } }, - "options.unicode1.unicode1": { + "options.unicode.unicode1": { "clearable": true, "type": "input" }, - "options.unicode1.unicode2": { + "options.unicode.unicode2": { "clearable": true, "type": "input" }, - "options.unicode1.unicode3": { + "options.unicode.unicode3": { "clearable": true, "type": "input" }, diff --git a/tests/dict/data/unicode1_leadership_requires_disabled_value.py b/tests/dict/data/unicode1_leadership_requires_disabled_value.py new file mode 100644 index 0000000..1c0696c --- /dev/null +++ b/tests/dict/data/unicode1_leadership_requires_disabled_value.py @@ -0,0 +1,33 @@ +from tiramisu import StrOption, OptionDescription, Leadership, Calculation, ParamValue, ParamOption, Params, calc_value + + +def get_description(): + """generate description for this test + """ + option = StrOption('unicode', "Values 'test' must show 'Unicode follower 3'", multi=True) + option1 = StrOption('unicode1', "Unicode follower 1", multi=True) + option2 = StrOption('unicode2', "Unicode follower 2", multi=True) + disabled_property = Calculation(calc_value, + Params(ParamValue('disabled'), + kwargs={'condition': ParamOption(option, todict=True), + 'expected': ParamValue('test'), + 'reverse_condition': ParamValue(True)})) + option3 = StrOption('unicode3', "Unicode follower 3", properties=(disabled_property,), multi=True) + descr1 = Leadership("unicode", "Common configuration 1", + [option, option1, option2, option3]) + descr = OptionDescription("options", "Common configuration 2", [descr1]) + descr = OptionDescription("unicode1_leadership_requires_disabled_value", "Leader followers with Unicode follower 3 disabled when Unicode follower 2 is test and modified value", [descr]) + return descr + + +async def get_values(api, allpath=False): + if allpath: + root = 'unicode1_leadership_requires_disabled_value.' + else: + root = '' + await api.option(root + 'options.unicode.unicode').value.set([u'test', u'val2']) + await api.option(root + 'options.unicode.unicode1', 0).value.set(u'super1') + await api.option(root + 'options.unicode.unicode1', 1).value.set(u'super2') + await api.option(root + 'options.unicode.unicode2', 0).value.set(u'pas test') + await api.option(root + 'options.unicode.unicode2', 1).value.set(u'test') + await api.option(root + 'options.unicode.unicode3', 1).value.set(u'super') diff --git a/tests/dict/data/unicode1_leadership_requires_follower.json b/tests/dict/data/unicode1_leadership_requires_follower.json index 253ccb5..7842097 100644 --- a/tests/dict/data/unicode1_leadership_requires_follower.json +++ b/tests/dict/data/unicode1_leadership_requires_follower.json @@ -30,7 +30,10 @@ }, "model": { "options.unicode1.unicode1": { - "required": true + "required": true, + "properties": [ + "unique" + ] } }, "global": { diff --git a/tests/dict/data/unicode1_leadership_requires_follower.py b/tests/dict/data/unicode1_leadership_requires_follower.py index 3cc68a8..fc2ad9e 100644 --- a/tests/dict/data/unicode1_leadership_requires_follower.py +++ b/tests/dict/data/unicode1_leadership_requires_follower.py @@ -1,5 +1,4 @@ -from tiramisu.option import StrOption, OptionDescription -from tiramisu import Leadership +from tiramisu import StrOption, OptionDescription, Leadership, Calculation, ParamValue, ParamOption, Params, calc_value def get_description(): @@ -7,11 +6,12 @@ def get_description(): """ option1 = StrOption('unicode1', "Values 'test' must show 'Unicode follower 2'", multi=True) option2 = StrOption('unicode2', "Unicode follower 1", multi=True) - option3 = StrOption('unicode3', "Unicode follower 2", multi=True, - requires=[{'option': option1, - 'expected': u'test', - 'action': 'hidden', - 'inverse': True}]) + hidden_property = Calculation(calc_value, + Params(ParamValue('hidden'), + kwargs={'condition': ParamOption(option1, todict=True), + 'expected': ParamValue('test'), + 'reverse_condition': ParamValue(True)})) + option3 = StrOption('unicode3', "Unicode follower 2", multi=True, properties=(hidden_property,)) descr1 = Leadership("unicode1", "Common configuration", [option1, option2, option3]) descr = OptionDescription("options", "Common configuration", [descr1]) diff --git a/tests/dict/data/unicode1_leadership_requires_follower_value.json b/tests/dict/data/unicode1_leadership_requires_follower_value.json index e95319a..758ee65 100644 --- a/tests/dict/data/unicode1_leadership_requires_follower_value.json +++ b/tests/dict/data/unicode1_leadership_requires_follower_value.json @@ -31,6 +31,9 @@ "model": { "options.unicode1.unicode1": { "required": true, + "properties": [ + "unique" + ], "value": [ "test", "pas test" @@ -49,8 +52,8 @@ "owner": "user" }, "1": { - "display": false, - "hidden": true + "hidden": true, + "display": false } } }, diff --git a/tests/dict/data/unicode1_leadership_requires_follower_value.py b/tests/dict/data/unicode1_leadership_requires_follower_value.py index d9661d6..b93c480 100644 --- a/tests/dict/data/unicode1_leadership_requires_follower_value.py +++ b/tests/dict/data/unicode1_leadership_requires_follower_value.py @@ -1,5 +1,4 @@ -from tiramisu.option import StrOption, OptionDescription -from tiramisu import Leadership +from tiramisu import StrOption, OptionDescription, Leadership, Calculation, ParamValue, ParamOption, Params, calc_value def get_description(): @@ -7,15 +6,16 @@ def get_description(): """ option1 = StrOption('unicode1', "Values 'test' must show 'Unicode follower 2'", multi=True) option2 = StrOption('unicode2', "Unicode follower 1", multi=True) - option3 = StrOption('unicode3', "Unicode follower 2", multi=True, - requires=[{'option': option1, - 'expected': u'test', - 'action': 'hidden', - 'inverse': True}]) + hidden_property = Calculation(calc_value, + Params(ParamValue('hidden'), + kwargs={'condition': ParamOption(option1, todict=True), + 'expected': ParamValue('test'), + 'reverse_condition': ParamValue(True)})) + option3 = StrOption('unicode3', "Unicode follower 2", multi=True, properties=(hidden_property,)) descr1 = Leadership("unicode1", "Common configuration", [option1, option2, option3]) descr = OptionDescription("options", "Common configuration", [descr1]) - descr = OptionDescription("unicode1_leadership_requires_follower_value", "Leader follower requires follower with leader value", [descr]) + descr = OptionDescription("unicode1_leadership_requires_follower_value", "Leader follower requires follower with leader", [descr]) return descr diff --git a/tests/dict/data/unicode1_leadership_requires_followers.json b/tests/dict/data/unicode1_leadership_requires_followers.json index 88c028f..2352239 100644 --- a/tests/dict/data/unicode1_leadership_requires_followers.json +++ b/tests/dict/data/unicode1_leadership_requires_followers.json @@ -30,7 +30,10 @@ }, "model": { "options.unicode1.unicode1": { - "required": true + "required": true, + "properties": [ + "unique" + ] } }, "global": { diff --git a/tests/dict/data/unicode1_leadership_requires_followers.py b/tests/dict/data/unicode1_leadership_requires_followers.py index 6a49dd7..9d71d6f 100644 --- a/tests/dict/data/unicode1_leadership_requires_followers.py +++ b/tests/dict/data/unicode1_leadership_requires_followers.py @@ -1,5 +1,4 @@ -from tiramisu.option import StrOption, OptionDescription -from tiramisu import Leadership +from tiramisu import StrOption, OptionDescription, Leadership, Calculation, ParamValue, ParamOption, Params, calc_value def get_description(): @@ -7,11 +6,12 @@ def get_description(): """ option1 = StrOption('unicode1', "Unicode leader", multi=True) option2 = StrOption('unicode2', "Values 'test' must show 'Unicode follower 2'", multi=True) - option3 = StrOption('unicode3', "Unicode follower 2", multi=True, - requires=[{'option': option2, - 'expected': u'test', - 'action': 'hidden', - 'inverse': True}]) + hidden_property = Calculation(calc_value, + Params(ParamValue('hidden'), + kwargs={'condition': ParamOption(option2, todict=True), + 'expected': ParamValue('test'), + 'reverse_condition': ParamValue(True)})) + option3 = StrOption('unicode3', "Unicode follower 2", multi=True, properties=(hidden_property,)) descr1 = Leadership("unicode1", "Common configuration", [option1, option2, option3]) descr = OptionDescription("options", "Common configuration", [descr1]) diff --git a/tests/dict/data/unicode1_leadership_requires_leader.py b/tests/dict/data/unicode1_leadership_requires_leader.py deleted file mode 100644 index 45b5e56..0000000 --- a/tests/dict/data/unicode1_leadership_requires_leader.py +++ /dev/null @@ -1,19 +0,0 @@ -from tiramisu.option import StrOption, OptionDescription -from tiramisu import Leadership - - -def get_description(): - """generate description for this test - """ - option = StrOption('unicode', "Value 'test' must show leader") - option1 = StrOption('unicode1', "Unicode leader", multi=True, requires=[{'option': option, - 'expected': u'test', - 'action': 'hidden', - 'inverse': True}]) - option2 = StrOption('unicode2', "Unicode follower 1", multi=True) - option3 = StrOption('unicode3', "Unicode follower 2", multi=True) - descr1 = Leadership("unicode1", "Common configuration", - [option1, option2, option3]) - descr = OptionDescription("options", "Common configuration", [option, descr1]) - descr = OptionDescription("unicode1_leadership_requires_leader", "Leader follower with requirement on leader", [descr]) - return descr diff --git a/tests/dict/data/unicode1_leadership_requires_value.json b/tests/dict/data/unicode1_leadership_requires_value.json index dfa26dc..c5c2974 100644 --- a/tests/dict/data/unicode1_leadership_requires_value.json +++ b/tests/dict/data/unicode1_leadership_requires_value.json @@ -36,6 +36,9 @@ "model": { "options.unicode.unicode": { "required": true, + "properties": [ + "unique" + ], "value": [ "test", "val2" @@ -64,8 +67,8 @@ }, "options.unicode.unicode3": { "1": { - "display": false, "hidden": true, + "display": false, "value": "super", "owner": "user" } diff --git a/tests/dict/data/unicode1_leadership_requires_value.py b/tests/dict/data/unicode1_leadership_requires_value.py index ef0c9d7..4f6596f 100644 --- a/tests/dict/data/unicode1_leadership_requires_value.py +++ b/tests/dict/data/unicode1_leadership_requires_value.py @@ -1,5 +1,4 @@ -from tiramisu.option import StrOption, OptionDescription -from tiramisu import Leadership +from tiramisu import StrOption, OptionDescription, Leadership, Calculation, ParamValue, ParamOption, Params, calc_value def get_description(): @@ -8,11 +7,12 @@ def get_description(): option = StrOption('unicode', "Values 'test' must show 'Unicode follower 3'", multi=True) option1 = StrOption('unicode1', "Unicode follower 1", multi=True) option2 = StrOption('unicode2', "Unicode follower 2", multi=True) - option3 = StrOption('unicode3', "Unicode follower 3", requires=[{'option': option, - 'expected': u'test', - 'action': 'hidden', - 'inverse': True}], - multi=True) + hidden_property = Calculation(calc_value, + Params(ParamValue('hidden'), + kwargs={'condition': ParamOption(option, todict=True), + 'expected': ParamValue('test'), + 'reverse_condition': ParamValue(True)})) + option3 = StrOption('unicode3', "Unicode follower 3", properties=(hidden_property,), multi=True) descr1 = Leadership("unicode", "Common configuration 1", [option, option1, option2, option3]) descr = OptionDescription("options", "Common configuration 2", [descr1]) diff --git a/tests/dict/data/unicode1_multi_requires.json b/tests/dict/data/unicode1_multi_requires.json index 3df4154..bcd74f0 100644 --- a/tests/dict/data/unicode1_multi_requires.json +++ b/tests/dict/data/unicode1_multi_requires.json @@ -19,8 +19,11 @@ "model": { "options.unicode2": { "required": true, - "display": false, - "hidden": true + "properties": [ + "unique" + ], + "hidden": true, + "display": false } }, "global": { diff --git a/tests/dict/data/unicode1_multi_requires.py b/tests/dict/data/unicode1_multi_requires.py index 893274d..f8c3254 100644 --- a/tests/dict/data/unicode1_multi_requires.py +++ b/tests/dict/data/unicode1_multi_requires.py @@ -1,15 +1,16 @@ -from tiramisu.option import StrOption, OptionDescription +from tiramisu import StrOption, OptionDescription, Calculation, ParamValue, ParamOption, Params, calc_value def get_description(): """generate description for this test """ option1 = StrOption('unicode1', "Value 'test' must show Unicode 2") - option2 = StrOption('unicode2', "Unicode 2", requires=[{'option': option1, - 'expected': u'test', - 'action': 'hidden', - 'inverse': True}], - multi=True) + hidden_property = Calculation(calc_value, + Params(ParamValue('hidden'), + kwargs={'condition': ParamOption(option1, todict=True), + 'expected': ParamValue('test'), + 'reverse_condition': ParamValue(True)})) + option2 = StrOption('unicode2', "Unicode 2", properties=(hidden_property,), multi=True) descr1 = OptionDescription("options", "Common configuration", [option1, option2]) descr = OptionDescription("unicode1_multi_requires", "Unicode multi with requirement", [descr1]) return descr diff --git a/tests/dict/data/unicode1_optiondescription_requires.json b/tests/dict/data/unicode1_optiondescription_requires.json index 3414661..654c510 100644 --- a/tests/dict/data/unicode1_optiondescription_requires.json +++ b/tests/dict/data/unicode1_optiondescription_requires.json @@ -27,7 +27,6 @@ }, "model": { "unicode1": { - "display": false, "properties": [ "hidden" ] diff --git a/tests/dict/data/unicode1_optiondescription_requires.py b/tests/dict/data/unicode1_optiondescription_requires.py index b5f07e1..12216cf 100644 --- a/tests/dict/data/unicode1_optiondescription_requires.py +++ b/tests/dict/data/unicode1_optiondescription_requires.py @@ -1,4 +1,4 @@ -from tiramisu.option import StrOption, OptionDescription +from tiramisu import StrOption, OptionDescription, Calculation, ParamValue, ParamOption, Params, calc_value def get_description(): @@ -8,10 +8,11 @@ def get_description(): descr1 = OptionDescription("options", "Common configuration", [option1]) option2 = StrOption('unicode2', "Unicode 2") option3 = StrOption('unicode3', "Unicode 3") - descr2 = OptionDescription("unicode1", "OptionDescription with 2 options", - [option2, option3], requires=[{'option': option1, - 'expected': u'test', - 'action': 'hidden', - 'inverse': True}]) + hidden_property = Calculation(calc_value, + Params(ParamValue('hidden'), + kwargs={'condition': ParamOption(option1, todict=True), + 'expected': ParamValue('test'), + 'reverse_condition': ParamValue(True)})) + descr2 = OptionDescription("unicode1", "OptionDescription with 2 options", [option2, option3], properties=(hidden_property,)) descr = OptionDescription("unicode1_optiondescription_requires", "OptionDesciption with requirement", [descr1, descr2]) return descr diff --git a/tests/dict/data/unicode1_requires.py b/tests/dict/data/unicode1_requires.py index 07d1fd5..657a206 100644 --- a/tests/dict/data/unicode1_requires.py +++ b/tests/dict/data/unicode1_requires.py @@ -1,14 +1,16 @@ -from tiramisu.option import StrOption, OptionDescription +from tiramisu import StrOption, OptionDescription, Calculation, ParamValue, ParamOption, Params, calc_value def get_description(): """generate description for this test """ option1 = StrOption('unicode1', "Value 'test' must show Unicode 2") - option2 = StrOption('unicode2', "Unicode 2", requires=[{'option': option1, - 'expected': u'test', - 'action': 'hidden', - 'inverse': True}]) + hidden_property = Calculation(calc_value, + Params(ParamValue('hidden'), + kwargs={'condition': ParamOption(option1, todict=True), + 'expected': ParamValue('test'), + 'reverse_condition': ParamValue(True)})) + option2 = StrOption('unicode2', "Unicode 2", properties=(hidden_property,)) descr1 = OptionDescription("options", "Common configuration", [option1, option2]) descr = OptionDescription("unicode1_requires", "Unicode with requirement", [descr1]) return descr diff --git a/tests/dict/test_json.py b/tests/dict/test_json.py index dda2ab0..91ceb23 100644 --- a/tests/dict/test_json.py +++ b/tests/dict/test_json.py @@ -31,7 +31,7 @@ def list_data(ext='.py'): ret = [] for filename in filenames: # if filename.endswith(ext) and not filename.startswith('__'): - if filename.endswith(ext) and not filename.startswith('__') and not 'require' in filename and not 'not_equal' in filename and not 'callback' in filename and not filename == 'unicode2_copy.py' and not filename == 'unicode2_multi_copy.py': + if filename.endswith(ext) and not filename.startswith('__') and not 'not_equal' in filename and not 'callback' in filename and not filename == 'unicode2_copy.py' and not filename == 'unicode2_multi_copy.py': ret.append(filename) return ret diff --git a/tests/test_cache.py b/tests/test_cache.py index 36287a1..d1046fa 100644 --- a/tests/test_cache.py +++ b/tests/test_cache.py @@ -401,9 +401,9 @@ async def test_cache_leader_and_followers(): values = cfg._config_bag.context._impl_values_cache settings = cfg._config_bag.context._impl_properties_cache compare(settings.get_cached(), {None: {None: (global_props, None)}, - 'val1': {None: (val1_props, None)}, - 'val1.val1': {None: (val1_val1_props, None)}, - 'val1.val2': {idx_val2: (val1_val2_props, None)}}) + 'val1': {None: (val1_props, None)}, + 'val1.val1': {None: (val1_val1_props, None)}, + 'val1.val2': {idx_val2: (val1_val2_props, None)}}) # len is 0 so don't get any value compare(values.get_cached(), {'val1.val1': {None: ([], None)}}) # diff --git a/tests/test_config_api.py b/tests/test_config_api.py index e73cf38..ef1bcb8 100644 --- a/tests/test_config_api.py +++ b/tests/test_config_api.py @@ -87,11 +87,7 @@ async def test_make_dict(config_type): d2 = await cfg.value.dict(flatten=True) assert d2 == {'a': True, 'int': 43} if config_type == 'tiramisu': - # FIXME - with pytest.raises(ValueError): - d2 = await cfg.value.dict(withvalue="3") - d = await cfg.forcepermissive.value.dict() - assert d == {"s1.a": True, "s1.b": False, "int": 43} + assert await cfg.forcepermissive.value.dict() == {"s1.a": True, "s1.b": False, "int": 43} @pytest.mark.asyncio @@ -113,23 +109,6 @@ async def test_make_dict_with_disabled(config_type): assert await cfg.unrestraint.value.dict() == {"int": 42, "s1.a": False, "s1.b": False, "s2.a": False, "s2.b": False} -@pytest.mark.asyncio -async def test_make_dict_with_disabled_withoption(): - descr = OptionDescription("opt", "", [ - OptionDescription("s1", "", [ - BoolOption("a", "", default=False), - BoolOption("b", "", default=False, properties=('disabled',))]), - OptionDescription("s2", "", [ - BoolOption("a", "", default=False), - BoolOption("b", "", default=False)], properties=('disabled',)), - IntOption("int", "", default=42)]) - cfg = await Config(descr) - await cfg.property.read_only() - assert await cfg.value.dict(withoption="a") == {"s1.a": False} - assert await cfg.forcepermissive.value.dict(withoption="a") == {"s1.a": False} - assert await cfg.unrestraint.value.dict(withoption="a") == {"s1.a": False, "s1.b": False, "s2.a": False, "s2.b": False} - - @pytest.mark.asyncio async def test_make_dict_with_disabled_in_callback(config_type): descr = OptionDescription("opt", "", [ diff --git a/tests/test_dyn_optiondescription.py b/tests/test_dyn_optiondescription.py index 4ec3aa7..df25c90 100644 --- a/tests/test_dyn_optiondescription.py +++ b/tests/test_dyn_optiondescription.py @@ -9,7 +9,7 @@ from tiramisu import BoolOption, StrOption, ChoiceOption, IPOption, \ StrOption, PortOption, BroadcastOption, DomainnameOption, \ EmailOption, URLOption, UsernameOption, FilenameOption, SymLinkOption, \ OptionDescription, DynOptionDescription, SynDynOption, submulti, Leadership, \ - Config, Params, ParamOption, ParamValue, ParamSuffix, ParamSelfOption, Calculation, calc_value + Config, Params, ParamOption, ParamValue, ParamSuffix, ParamSelfOption, ParamIndex, Calculation, calc_value from tiramisu.error import PropertiesOptionError, ConfigError, ConflictError from tiramisu.storage import list_sessions @@ -761,9 +761,6 @@ async def test_makedict_dyndescription_context(): await cfg.option('od.dodval1.stval1').value.set('yes') assert await cfg.value.dict() == {'od.val1': ['val1', 'val2'], 'od.dodval1.stval1': 'yes', 'od.dodval2.stval2': None} assert await cfg.value.dict(flatten=True) == {'val1': ['val1', 'val2'], 'stval1': 'yes', 'stval2': None} - assert await cfg.value.dict(withoption='stval1') == {'od.dodval1.stval1': 'yes'} - assert await cfg.option('od').value.dict(withoption='stval1') == {'dodval1.stval1': 'yes'} - assert await cfg.option('od.dodval1').value.dict(withoption='stval1') == {'stval1': 'yes'} @pytest.mark.asyncio @@ -1549,3 +1546,89 @@ async def test_leadership_callback_samegroup_dyndescription_convert(): assert await cfg.option('od.stval1.st1val1.st2val1', 0).owner.get() == owner assert await cfg.option('od.stval1.st1val1.st3val1', 0).owner.isdefault() assert await cfg.option('od.stval2.st1val2.st1val2').owner.isdefault() + + +@pytest.mark.asyncio +async def test_dyn_with_leader_hidden_in_config(): + 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, properties=('hidden',)) + interface1 = Leadership('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0], properties=('hidden',)) + dyn = DynOptionDescription('leader', '', [interface1], suffixes=Calculation(return_list)) + od = OptionDescription('root', '', [dyn]) + cfg = await Config(od) + await cfg.property.read_write() + await cfg.permissive.add('hidden') + assert await cfg.forcepermissive.option('leaderval1.ip_admin_eth0val1.ip_admin_eth0val1').value.get() == [] + await cfg.forcepermissive.option('leaderval1.ip_admin_eth0val1.ip_admin_eth0val1').value.set(['192.168.1.1']) + assert await cfg.forcepermissive.option('leaderval1.ip_admin_eth0val1.netmask_admin_eth0val1', 0).value.get() is None + with pytest.raises(PropertiesOptionError): + await cfg.option('leaderval1.ip_admin_eth0val1.ip_admin_eth0val1').value.get() + with pytest.raises(PropertiesOptionError): + await cfg.option('leaderval1.ip_admin_eth0val1.netmask_admin_eth0val1', 0).value.get() + await cfg.value.dict(leader_to_list=True) == {'leaderval1.ip_admin_eth0val1.ip_admin_eth0val1': [{'leaderval1.ip_admin_eth0val1.ip_admin_eth0val1': '192.168.1.1'}], + 'leaderval2.ip_admin_eth0val2.ip_admin_eth0val2': [{'leaderval2.ip_admin_eth0val2.ip_admin_eth0val2': '192.168.1.1'}]} + + +@pytest.mark.asyncio +async def test_dyn_leadership_requires(): + ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True, properties=('notunique',)) + disabled_property = Calculation(calc_value, + Params(ParamValue('disabled'), + kwargs={'condition': ParamOption(ip_admin_eth0, notraisepropertyerror=True), + 'expected': ParamValue('192.168.1.1'), + 'no_condition_is_invalid': ParamValue(True), + 'index': ParamIndex()})) + netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True, properties=(disabled_property,)) + interface1 = Leadership('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0]) + dyn = DynOptionDescription('leader', '', [interface1], suffixes=Calculation(return_list)) + od = OptionDescription('toto', '', [dyn]) + cfg = await Config(od) + await cfg.property.read_write() + assert await cfg.option('leaderval1.ip_admin_eth0val1.ip_admin_eth0val1').value.get() == [] + await cfg.option('leaderval1.ip_admin_eth0val1.ip_admin_eth0val1').value.set(['192.168.1.2']) + assert await cfg.option('leaderval1.ip_admin_eth0val1.netmask_admin_eth0val1', 0).value.get() is None + assert await cfg.option('leaderval1.ip_admin_eth0val1.ip_admin_eth0val1').value.get() == ['192.168.1.2'] + # + await cfg.option('leaderval1.ip_admin_eth0val1.ip_admin_eth0val1').value.set(['192.168.1.2', '192.168.1.1']) + assert await cfg.option('leaderval1.ip_admin_eth0val1.netmask_admin_eth0val1', 0).value.get() is None + with pytest.raises(PropertiesOptionError): + await cfg.option('leaderval1.ip_admin_eth0val1.netmask_admin_eth0val1', 1).value.get() + # + await cfg.option('leaderval1.ip_admin_eth0val1.ip_admin_eth0val1').value.set(['192.168.1.2', '192.168.1.2']) + assert await cfg.option('leaderval1.ip_admin_eth0val1.netmask_admin_eth0val1', 0).value.get() is None + assert await cfg.option('leaderval1.ip_admin_eth0val1.netmask_admin_eth0val1', 1).value.get() is None + await cfg.option('leaderval1.ip_admin_eth0val1.netmask_admin_eth0val1', 1).value.set('255.255.255.255') + assert await cfg.option('leaderval1.ip_admin_eth0val1.netmask_admin_eth0val1', 1).value.get() == '255.255.255.255' + assert await cfg.value.dict() == {'leaderval1.ip_admin_eth0val1.ip_admin_eth0val1': ['192.168.1.2', '192.168.1.2'], + 'leaderval1.ip_admin_eth0val1.netmask_admin_eth0val1': [None, '255.255.255.255'], + 'leaderval2.ip_admin_eth0val2.ip_admin_eth0val2': [], + 'leaderval2.ip_admin_eth0val2.netmask_admin_eth0val2': []} + + ret = await cfg.value.dict(leader_to_list=True) + assert ret == {'leaderval1.ip_admin_eth0val1.ip_admin_eth0val1': [{'leaderval1.ip_admin_eth0val1.ip_admin_eth0val1': '192.168.1.2', 'leaderval1.ip_admin_eth0val1.netmask_admin_eth0val1': None}, + {'leaderval1.ip_admin_eth0val1.ip_admin_eth0val1': '192.168.1.2', 'leaderval1.ip_admin_eth0val1.netmask_admin_eth0val1': '255.255.255.255'}], + 'leaderval2.ip_admin_eth0val2.ip_admin_eth0val2': []} + + # + await cfg.option('leaderval1.ip_admin_eth0val1.ip_admin_eth0val1').value.set(['192.168.1.2', '192.168.1.1']) + assert await cfg.option('leaderval1.ip_admin_eth0val1.netmask_admin_eth0val1', 0).value.get() is None + with pytest.raises(PropertiesOptionError): + await cfg.option('leaderval1.ip_admin_eth0val1.netmask_admin_eth0val1', 1).value.get() + ret = await cfg.value.dict() + assert set(ret.keys()) == set(['leaderval1.ip_admin_eth0val1.ip_admin_eth0val1', 'leaderval1.ip_admin_eth0val1.netmask_admin_eth0val1', 'leaderval2.ip_admin_eth0val2.ip_admin_eth0val2', 'leaderval2.ip_admin_eth0val2.netmask_admin_eth0val2']) + assert ret['leaderval1.ip_admin_eth0val1.ip_admin_eth0val1'] == ['192.168.1.2', '192.168.1.1'] + assert len(ret['leaderval1.ip_admin_eth0val1.netmask_admin_eth0val1']) == 2 + assert ret['leaderval1.ip_admin_eth0val1.netmask_admin_eth0val1'][0] is None + assert isinstance(ret['leaderval1.ip_admin_eth0val1.netmask_admin_eth0val1'][1], PropertiesOptionError) + del ret['leaderval1.ip_admin_eth0val1.netmask_admin_eth0val1'][1] + del ret['leaderval1.ip_admin_eth0val1.netmask_admin_eth0val1'][0] + del ret['leaderval1.ip_admin_eth0val1.netmask_admin_eth0val1'] + assert await cfg.value.dict(leader_to_list=True) == {'leaderval1.ip_admin_eth0val1.ip_admin_eth0val1': [{'leaderval1.ip_admin_eth0val1.ip_admin_eth0val1': '192.168.1.2', + 'leaderval1.ip_admin_eth0val1.netmask_admin_eth0val1': None}, + {'leaderval1.ip_admin_eth0val1.ip_admin_eth0val1': '192.168.1.1'}], + 'leaderval2.ip_admin_eth0val2.ip_admin_eth0val2': []} + # + assert await cfg.value.dict(leader_to_list=True) == {'leaderval1.ip_admin_eth0val1.ip_admin_eth0val1': [{'leaderval1.ip_admin_eth0val1.ip_admin_eth0val1': '192.168.1.2', + 'leaderval1.ip_admin_eth0val1.netmask_admin_eth0val1': None}, + {'leaderval1.ip_admin_eth0val1.ip_admin_eth0val1': '192.168.1.1'}], + 'leaderval2.ip_admin_eth0val2.ip_admin_eth0val2': []} diff --git a/tests/test_leadership.py b/tests/test_leadership.py index f1205ff..5808c99 100644 --- a/tests/test_leadership.py +++ b/tests/test_leadership.py @@ -91,25 +91,6 @@ async def test_base_config(config_type): await cfg.send() -@pytest.mark.asyncio -async def test_make_dict_filter(): - descr = make_description() - cfg = await Config(descr) - await cfg.property.read_write() - subresult = {'numero_etab': None, 'nombre_interfaces': 1, - 'serveur_ntp': [], 'mode_conteneur_actif': False, - 'time_zone': 'Paris', 'nom_machine': 'eoleng', - 'activer_proxy_client': False} - result = {} - for key, value in subresult.items(): - result['general.' + key] = value - assert await cfg.option('creole').value.dict(withoption='numero_etab') == result - with pytest.raises(AttributeError): - await cfg.option('creole').value.dict(withoption='numero_etab', withvalue='toto') - assert await cfg.option('creole').value.dict(withoption='numero_etab', withvalue=None) == result - assert await cfg.option('creole.general').value.dict(withoption='numero_etab') == subresult - - @pytest.mark.asyncio async def test_get_group_type(): descr = make_description() @@ -289,6 +270,7 @@ async def test_groups_with_leader_make_dict(config_type): cfg = await Config(od) cfg = await get_config(cfg, config_type) assert await cfg.value.dict() == {'ip_admin_eth0.ip_admin_eth0': [], 'ip_admin_eth0.netmask_admin_eth0': []} + assert await cfg.value.dict(leader_to_list=True) == {'ip_admin_eth0.ip_admin_eth0': []} if config_type != 'tiramisu-api': # FIXME useful? already in leadership assert await cfg.option('ip_admin_eth0.ip_admin_eth0').value.len() == 0 @@ -299,6 +281,7 @@ async def test_groups_with_leader_make_dict(config_type): assert await cfg.option('ip_admin_eth0.ip_admin_eth0').value.len() == 2 assert await cfg.option('ip_admin_eth0.netmask_admin_eth0').value.len() == 2 assert await cfg.value.dict() == {'ip_admin_eth0.ip_admin_eth0': ['ip1', 'ip2'], 'ip_admin_eth0.netmask_admin_eth0': [None, None]} + assert await cfg.value.dict(leader_to_list=True) == {'ip_admin_eth0.ip_admin_eth0': [{'ip_admin_eth0.ip_admin_eth0': 'ip1', 'ip_admin_eth0.netmask_admin_eth0': None}, {'ip_admin_eth0.ip_admin_eth0': 'ip2', 'ip_admin_eth0.netmask_admin_eth0': None}]} if config_type == 'tiramisu-api': await cfg.send() @@ -365,6 +348,7 @@ async def test_groups_with_leader_hidden_in_config(): await cfg.option('ip_admin_eth0.ip_admin_eth0').value.get() with pytest.raises(PropertiesOptionError): await cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get() + await cfg.value.dict(leader_to_list=True) == {'ip_admin_eth0.ip_admin_eth0': [{'ip_admin_eth0.ip_admin_eth0': '192.168.1.1'}]} @pytest.mark.asyncio diff --git a/tests/test_requires.py b/tests/test_requires.py index eac88af..bd9426c 100644 --- a/tests/test_requires.py +++ b/tests/test_requires.py @@ -1085,7 +1085,9 @@ async def test_leadership_requires(config_type): await cfg.option('ip_admin_eth0.netmask_admin_eth0', 1).value.set('255.255.255.255') assert await cfg.option('ip_admin_eth0.netmask_admin_eth0', 1).value.get() == '255.255.255.255' assert await cfg.value.dict() == {'ip_admin_eth0.ip_admin_eth0': ['192.168.1.2', '192.168.1.2'], - 'ip_admin_eth0.netmask_admin_eth0': [None, '255.255.255.255']} + 'ip_admin_eth0.netmask_admin_eth0': [None, '255.255.255.255']} + assert await cfg.value.dict(leader_to_list=True) == {'ip_admin_eth0.ip_admin_eth0': [{'ip_admin_eth0.ip_admin_eth0': '192.168.1.2', 'ip_admin_eth0.netmask_admin_eth0': None}, + {'ip_admin_eth0.ip_admin_eth0': '192.168.1.2', 'ip_admin_eth0.netmask_admin_eth0': '255.255.255.255'}]} # await cfg.option('ip_admin_eth0.ip_admin_eth0').value.set(['192.168.1.2', '192.168.1.1']) assert await cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get() is None @@ -1100,6 +1102,9 @@ async def test_leadership_requires(config_type): del ret['ip_admin_eth0.netmask_admin_eth0'][1] del ret['ip_admin_eth0.netmask_admin_eth0'][0] del ret['ip_admin_eth0.netmask_admin_eth0'] + assert await cfg.value.dict(leader_to_list=True) == {'ip_admin_eth0.ip_admin_eth0': [{'ip_admin_eth0.ip_admin_eth0': '192.168.1.2', + 'ip_admin_eth0.netmask_admin_eth0': None}, + {'ip_admin_eth0.ip_admin_eth0': '192.168.1.1'}]} # await cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).value.set('255.255.255.255') ret = await cfg.value.dict() @@ -1111,6 +1116,9 @@ async def test_leadership_requires(config_type): del ret['ip_admin_eth0.netmask_admin_eth0'][1] del ret['ip_admin_eth0.netmask_admin_eth0'][0] del ret['ip_admin_eth0.netmask_admin_eth0'] + assert await cfg.value.dict(leader_to_list=True) == {'ip_admin_eth0.ip_admin_eth0': [{'ip_admin_eth0.ip_admin_eth0': '192.168.1.2', + 'ip_admin_eth0.netmask_admin_eth0': '255.255.255.255'}, + {'ip_admin_eth0.ip_admin_eth0': '192.168.1.1'}]} @pytest.mark.asyncio diff --git a/tests/test_slots.py b/tests/test_slots.py index 967e228..3d8496d 100644 --- a/tests/test_slots.py +++ b/tests/test_slots.py @@ -144,7 +144,6 @@ async def test_slots_config(): option_bag = OptionBag() option_bag.set_option(od2, 'a', - None, ConfigBag(c._config_bag.context, None, None)) sc = await c._config_bag.context.get_subconfig(option_bag) assert isinstance(sc, SubConfig) diff --git a/tiramisu/api.py b/tiramisu/api.py index 6bae10e..3742c61 100644 --- a/tiramisu/api.py +++ b/tiramisu/api.py @@ -214,7 +214,8 @@ class _TiramisuOptionOptionDescription(CommonTiramisuOption): apply_requires=False) # do not check cache properties/permissives which are not save (unrestraint, ...) return await settings.calc_raises_properties(self._option_bag, - apply_requires=False) + apply_requires=False, + uncalculated=uncalculated) def __call__(self, name: str, @@ -347,13 +348,15 @@ class TiramisuOptionProperty(CommonTiramisuOption): self._settings = option_bag.config_bag.context.cfgimpl_get_settings() async def get(self, - only_raises=False): + only_raises=False, + uncalculated=False): """Get properties for an option""" await self._get_option() if not only_raises: return self._option_bag.properties # do not check cache properties/permissives which are not save (unrestraint, ...) - return await self._settings.calc_raises_properties(self._option_bag) + return await self._settings.calc_raises_properties(self._option_bag, + uncalculated=uncalculated) async def add(self, prop): """Add new property for an option""" @@ -510,8 +513,6 @@ class TiramisuOptionValue(CommonTiramisuOption): @option_type('optiondescription') async def dict(self, flatten=False, - withvalue=undefined, - withoption=None, withwarning: bool=False, fullpath=False): """Dict with path as key and value""" @@ -523,9 +524,7 @@ class TiramisuOptionValue(CommonTiramisuOption): config_bag.remove_warnings() return await subconfig.make_dict(config_bag=config_bag, flatten=flatten, - fullpath=fullpath, - withoption=withoption, - withvalue=withvalue) + fullpath=fullpath) @option_type('option') async def get(self): @@ -576,7 +575,6 @@ class TiramisuOptionValue(CommonTiramisuOption): for idx in range(length): soption_bag = OptionBag() soption_bag.set_option(option, - self._option_bag.path, idx, self._option_bag.config_bag) soption_bag.properties = await settings.getproperties(soption_bag) @@ -706,7 +704,6 @@ class TiramisuOption(CommonTiramisu, TiramisuConfig): path = self._subconfig._get_subpath(oname) option_bag = OptionBag() option_bag.set_option(option, - path, None, config_bag) subconfig = await self._subconfig.get_subconfig(option_bag) @@ -736,7 +733,6 @@ class TiramisuOption(CommonTiramisu, TiramisuConfig): settings = config_bag.context.cfgimpl_get_settings() option_bag = OptionBag() option_bag.set_option(opt, - opt.impl_getpath(), None, config_bag) option_bag.properties = await settings.getproperties(option_bag) @@ -761,7 +757,6 @@ class TiramisuOption(CommonTiramisu, TiramisuConfig): option = await self._get_option() option_bag = OptionBag() option_bag.set_option(option, - option.impl_getpath(), None, config_bag) subconfig = await self._subconfig.get_subconfig(option_bag) @@ -877,11 +872,10 @@ class TiramisuContextValue(TiramisuConfig): self._config_bag) async def dict(self, - flatten=False, - withvalue=undefined, - withoption=None, - withwarning: bool=False, - fullpath=False): + flatten=False, + withwarning: bool=False, + fullpath=False, + leader_to_list=False): """Dict with path as key and value""" config_bag = self._config_bag if not withwarning and 'warnings' in config_bag.properties: @@ -890,8 +884,7 @@ class TiramisuContextValue(TiramisuConfig): return await config_bag.context.make_dict(config_bag, flatten=flatten, fullpath=fullpath, - withoption=withoption, - withvalue=withvalue) + leader_to_list=leader_to_list) async def exportation(self, with_default_owner: bool=False): @@ -1146,7 +1139,6 @@ class TiramisuContextOption(TiramisuConfig): config_bag): option_bag = OptionBag() option_bag.set_option(opt, - opt.impl_getpath(), None, config_bag) settings = config_bag.context.cfgimpl_get_settings() diff --git a/tiramisu/autolib.py b/tiramisu/autolib.py index 8133358..d1f7fad 100644 --- a/tiramisu/autolib.py +++ b/tiramisu/autolib.py @@ -202,7 +202,9 @@ async def manager_callback(callbk: Union[ParamOption, ParamValue], if config_bag is undefined: return undefined path = option.impl_getpath() - option_bag = await get_option_bag(config_bag, option, path, apply_index) + option_bag = await get_option_bag(config_bag, + option, + apply_index) option_bag.config_bag.unrestraint() option_bag.config_bag.remove_validation() # if we are in properties calculation, cannot calculated properties @@ -233,7 +235,6 @@ async def manager_callback(callbk: Union[ParamOption, ParamValue], async def get_option_bag(config_bag, opt, - path, index_): # don't validate if option is option that we tried to validate config_bag = config_bag.copy() @@ -242,7 +243,6 @@ async def manager_callback(callbk: Union[ParamOption, ParamValue], #config_bag.properties -= {'warnings'} option_bag = OptionBag() option_bag.set_option(opt, - path, index_, config_bag) option_bag.properties = await config_bag.context.cfgimpl_get_settings().getproperties(option_bag) @@ -292,7 +292,9 @@ async def manager_callback(callbk: Union[ParamOption, ParamValue], index_ = None with_index = False path = callbk_option.impl_getpath() - option_bag = await get_option_bag(config_bag, callbk_option, path, index_) + option_bag = await get_option_bag(config_bag, + callbk_option, + index_) value = await get_value(callbk, option_bag, path) if with_index: value = value[index] diff --git a/tiramisu/config.py b/tiramisu/config.py index ac02b18..0efaed5 100644 --- a/tiramisu/config.py +++ b/tiramisu/config.py @@ -75,12 +75,10 @@ class SubConfig: if descr is not None and descr.impl_is_leadership(): leader = descr.get_leader() leaderpath = leader.impl_getname() - full_leaderpath = self._get_subpath(leaderpath) cconfig_bag = config_bag.copy() cconfig_bag.remove_validation() moption_bag = OptionBag() moption_bag.set_option(leader, - full_leaderpath, None, cconfig_bag) moption_bag.properties = await self.cfgimpl_get_settings().getproperties(moption_bag) @@ -118,10 +116,8 @@ class SubConfig: doption = option.to_dynoption(subpath, suffix, option) - doption_path = doption.impl_getpath() doption_bag = OptionBag() doption_bag.set_option(doption, - doption_path, option_bag.index, option_bag.config_bag) doption_bag.properties = await self.cfgimpl_get_settings().getproperties(doption_bag) @@ -139,10 +135,8 @@ class SubConfig: doption = option.to_dynoption(subpath, suffix, dynopt) - doption_path = doption.impl_getpath() doption_bag = OptionBag() doption_bag.set_option(doption, - doption_path, option_bag.index, option_bag.config_bag) doption_bag.properties = await self.cfgimpl_get_settings().getproperties(doption_bag) @@ -150,10 +144,8 @@ class SubConfig: resetted_opts, doption_bag) else: - option_path = option.impl_getpath() doption_bag = OptionBag() doption_bag.set_option(option, - option_path, option_bag.index, option_bag.config_bag) doption_bag.properties = await self.cfgimpl_get_settings().getproperties(doption_bag) @@ -194,9 +186,7 @@ class SubConfig: option = await self.cfgimpl_get_description().get_child(step, config_bag, self.cfgimpl_get_path()) - subpath = self._get_subpath(step) option_bag.set_option(option, - subpath, None, config_bag) option_bag.properties = await self.cfgimpl_get_settings().getproperties(option_bag) @@ -285,7 +275,6 @@ class SubConfig: if option.impl_is_symlinkoption(): soption_bag = OptionBag() soption_bag.set_option(option.impl_getopt(), - None, option_bag.index, config_bag) soption_bag.properties = await self.cfgimpl_get_settings().getproperties(soption_bag) @@ -316,7 +305,6 @@ class SubConfig: for idx in range(length): soption_bag = OptionBag() soption_bag.set_option(option, - option_bag.path, idx, config_bag) soption_bag.properties = await self.cfgimpl_get_settings().getproperties(soption_bag) @@ -374,7 +362,6 @@ class SubConfig: option_bag = OptionBag() path = option.impl_getpath() option_bag.set_option(option, - path, None, config_bag) option_bag.properties = await self.cfgimpl_get_settings().getproperties(option_bag) @@ -413,116 +400,90 @@ class SubConfig: async def make_dict(self, config_bag, flatten=False, - _currpath=None, - withoption=None, - withvalue=undefined, - fullpath=False): + fullpath=False, + leader_to_list=False): """exports the whole config into a `dict` :returns: dict of Option's name (or path) and values """ pathsvalues = {} - if _currpath is None: - _currpath = [] - if withoption is None and withvalue is not undefined: - raise ValueError(_("make_dict can't filtering with value without " - "option")) - context = self.cfgimpl_get_context() - await self._make_dict(context, - config_bag, + await self._make_dict(config_bag, + [], flatten, - _currpath, - withoption, - withvalue, fullpath, - pathsvalues) + pathsvalues, + leader_to_list) return pathsvalues async def _make_dict(self, - context, config_bag, - flatten, _currpath, - withoption, - withvalue, + flatten, fullpath, - pathsvalues): - if withoption is not None: - # Find all option with criteria - # retrieve OptionDescription and make_dict on it - mypath = self.cfgimpl_get_path() - async for path in context.find(bytype=None, - byname=withoption, - byvalue=withvalue, - _subpath=self.cfgimpl_get_path(False), - config_bag=config_bag): - path = '.'.join(path.split('.')[:-1]) - if '.' in path: - subconfig, subpath = await context.cfgimpl_get_home_by_path(path, - config_bag) - else: - subconfig = context - subpath = path - opt = await subconfig.cfgimpl_get_description().get_child(subpath, - config_bag, - subconfig.cfgimpl_get_path()) + pathsvalues, + leader_to_list): + for opt in await self.cfgimpl_get_description().get_children(config_bag): + if opt.impl_is_optiondescription() and leader_to_list and opt.impl_is_leadership(): + children = await opt.get_children(config_bag) + leader = children[0] + loption_bag = OptionBag() + loption_bag.set_option(leader, + None, + config_bag) + loption_bag.properties = await self.cfgimpl_get_settings().getproperties(loption_bag) + leader_pathsvalues = {} + leader_currpath = _currpath + [leader.impl_getname()] + await self._make_sub_dict(leader_pathsvalues, + leader_currpath, + loption_bag, + flatten, + fullpath, + leader_to_list) + if not leader_pathsvalues: + continue + leader_name = list(leader_pathsvalues.keys())[0] + pathsvalues[leader_name] = [] + subconfig = await SubConfig(opt, + self._impl_context, + config_bag, + opt.impl_getpath()) + for idx, value in enumerate(leader_pathsvalues[leader_name]): + leadership_pathsvalues = {leader_name: value} + for follower_opt in children[1:]: + foption_bag = OptionBag() + foption_bag.set_option(follower_opt, + idx, + config_bag) + foption_bag.properties = await self.cfgimpl_get_settings().getproperties(foption_bag) + await subconfig._make_sub_dict(leadership_pathsvalues, + leader_currpath, + foption_bag, + flatten, + fullpath, + leader_to_list) + pathsvalues[leader_name].append(leadership_pathsvalues) + else: soption_bag = OptionBag() soption_bag.set_option(opt, - path, None, config_bag) soption_bag.properties = await self.cfgimpl_get_settings().getproperties(soption_bag) - if mypath is not None: - if mypath == path: - withoption = None - withvalue = undefined - break - else: - tmypath = mypath + '.' - assert path.startswith(tmypath), _('unexpected path "{0}", ' - 'should start with "{1}"' - '').format(path, mypath) - path = path[len(tmypath):] - await self._make_sub_dict(path, - pathsvalues, + await self._make_sub_dict(pathsvalues, _currpath, - flatten, soption_bag, - fullpath, - context, - withvalue) - - #withoption can be set to None below ! - if withoption is None: - children = await self.cfgimpl_get_description().get_children(config_bag) - for opt in children: - name = opt.impl_getname() - path = self._get_subpath(name) - soption_bag = OptionBag() - soption_bag.set_option(opt, - path, - None, - config_bag) - soption_bag.properties = await self.cfgimpl_get_settings().getproperties(soption_bag) - await self._make_sub_dict(name, - pathsvalues, - _currpath, flatten, - soption_bag, fullpath, - context, - withvalue) + leader_to_list) return pathsvalues async def _make_sub_dict(self, - name, pathsvalues, _currpath, - flatten, option_bag, + flatten, fullpath, - context, - withvalue): + leader_to_list): option = option_bag.option + name = option.impl_getname() if option.impl_is_optiondescription(): try: await self.cfgimpl_get_settings().validate_properties(option_bag) @@ -530,14 +491,12 @@ class SubConfig: self._impl_context, option_bag.config_bag, option_bag.path) - await subconfig._make_dict(context, - option_bag.config_bag, - flatten, + await subconfig._make_dict(option_bag.config_bag, _currpath + [name], - None, - withvalue, + flatten, fullpath, - pathsvalues) + pathsvalues, + leader_to_list) except PropertiesOptionError as err: if err.proptype in (['mandatory'], ['empty']): raise err @@ -554,7 +513,7 @@ class SubConfig: if flatten: name_ = option.impl_getname() elif fullpath: - name_ = self._get_subpath(name) + name_ = option.impl_getpath() else: name_ = '.'.join(_currpath + [name]) pathsvalues[name_] = ret @@ -879,7 +838,6 @@ class KernelGroupConfig(_CommonConfig): child.cfgimpl_get_path()) option_bag = OptionBag() option_bag.set_option(option, - path, index, cconfig_bag) option_bag.properties = await settings.getproperties(option_bag) @@ -977,7 +935,6 @@ class KernelGroupConfig(_CommonConfig): subconfig.cfgimpl_get_path()) option_bag = OptionBag() option_bag.set_option(option, - path, None, config_bag) option_bag.properties = await child.cfgimpl_get_settings().getproperties(option_bag) @@ -1061,7 +1018,6 @@ class KernelMixConfig(KernelGroupConfig): self.cfgimpl_get_path()) option_bag = OptionBag() option_bag.set_option(option, - path, index, config_bag) option_bag.properties = await self.cfgimpl_get_settings().getproperties(option_bag) @@ -1093,7 +1049,6 @@ class KernelMixConfig(KernelGroupConfig): child.cfgimpl_get_path()) moption_bag = OptionBag() moption_bag.set_option(option, - path, index, cconfig_bag) moption_bag.properties = await settings.getproperties(moption_bag) @@ -1155,7 +1110,6 @@ class KernelMixConfig(KernelGroupConfig): subconfig.cfgimpl_get_path()) option_bag = OptionBag() option_bag.set_option(option, - path, None, rconfig_bag) option_bag.properties = await self.cfgimpl_get_settings().getproperties(option_bag) @@ -1168,7 +1122,6 @@ class KernelMixConfig(KernelGroupConfig): subconfig.cfgimpl_get_path()) option_bag = OptionBag() option_bag.set_option(option, - path, None, rconfig_bag) option_bag.properties = await self.cfgimpl_get_settings().getproperties(option_bag) @@ -1188,7 +1141,6 @@ class KernelMixConfig(KernelGroupConfig): child.cfgimpl_get_path()) moption_bag = OptionBag() moption_bag.set_option(option, - path, None, rconfig_bag) moption_bag.properties = await self.cfgimpl_get_settings().getproperties(moption_bag) diff --git a/tiramisu/option/dynoptiondescription.py b/tiramisu/option/dynoptiondescription.py index aff3654..1866692 100644 --- a/tiramisu/option/dynoptiondescription.py +++ b/tiramisu/option/dynoptiondescription.py @@ -71,7 +71,6 @@ class DynOptionDescription(OptionDescription): config_bag: ConfigBag) -> List[str]: option_bag = OptionBag() option_bag.set_option(self, - self.impl_getpath(), None, config_bag) values = await self._suffixes.execute(option_bag) diff --git a/tiramisu/option/leadership.py b/tiramisu/option/leadership.py index d8cd85b..5a943f3 100644 --- a/tiramisu/option/leadership.py +++ b/tiramisu/option/leadership.py @@ -118,10 +118,8 @@ class Leadership(OptionDescription): config_bag = option_bag.config_bag.copy() config_bag.remove_validation() for follower in self.get_followers(): - follower_path = follower.impl_getpath() soption_bag = OptionBag() soption_bag.set_option(follower, - follower_path, None, config_bag) soption_bag.properties = await config_bag.context.cfgimpl_get_settings().getproperties(soption_bag) @@ -133,21 +131,22 @@ class Leadership(OptionDescription): value, option_bag, owner, - _commit) -> None: + _commit, + dyn=None) -> None: settings = option_bag.config_bag.context.cfgimpl_get_settings() if value: rgevalue = range(len(value)) - for follower in await self.get_children(option_bag.config_bag): + if dyn is None: + dyn = self + for follower in await dyn.get_children(option_bag.config_bag): foption_bag = OptionBag() foption_bag.set_option(follower, - follower.impl_getpath(), None, option_bag.config_bag) if 'force_store_value' in await settings.getproperties(foption_bag): for index in rgevalue: foption_bag = OptionBag() foption_bag.set_option(follower, - follower.impl_getpath(), index, option_bag.config_bag) foption_bag.properties = await settings.getproperties(foption_bag) @@ -171,7 +170,6 @@ class Leadership(OptionDescription): followerlen = await values._p_.get_max_length(follower_path) soption_bag = OptionBag() soption_bag.set_option(follower, - follower_path, index, config_bag) # do not check force_default_on_freeze or force_metaconfig_on_freeze diff --git a/tiramisu/option/option.py b/tiramisu/option/option.py index e8afd14..f330709 100644 --- a/tiramisu/option/option.py +++ b/tiramisu/option/option.py @@ -116,7 +116,6 @@ class Option(BaseOption): return option_bag = OptionBag() option_bag.set_option(self, - undefined, None, undefined) try: @@ -148,7 +147,6 @@ class Option(BaseOption): _setattr(self, '_default_multi', default_multi) option_bag = OptionBag() option_bag.set_option(self, - undefined, None, undefined) self.sync_impl_validate(default, diff --git a/tiramisu/option/optiondescription.py b/tiramisu/option/optiondescription.py index 3abf9c9..6252cef 100644 --- a/tiramisu/option/optiondescription.py +++ b/tiramisu/option/optiondescription.py @@ -117,7 +117,6 @@ class CacheOptionDescription(BaseOption): option_bag = OptionBag() leader = option.impl_get_leadership().get_leader() option_bag.set_option(leader, - leader.impl_getpath(), None, config_bag) option_bag.properties = frozenset() @@ -125,7 +124,6 @@ class CacheOptionDescription(BaseOption): for index in range(follower_len): option_bag = OptionBag() option_bag.set_option(option, - subpath, index, config_bag) option_bag.properties = frozenset() @@ -137,7 +135,6 @@ class CacheOptionDescription(BaseOption): else: option_bag = OptionBag() option_bag.set_option(option, - subpath, None, config_bag) option_bag.properties = frozenset() @@ -183,7 +180,7 @@ class OptionDescriptionWalk(CacheOptionDescription): async def get_children(self, config_bag: Union[ConfigBag, Undefined], - dyn: bool=True) -> Iterator[Union[BaseOption, SynDynOptionDescription]]: + dyn: bool=True) -> Union[BaseOption, SynDynOptionDescription]: if not dyn or config_bag is undefined or \ config_bag.context.cfgimpl_get_description() == self: subpath = '' diff --git a/tiramisu/option/syndynoptiondescription.py b/tiramisu/option/syndynoptiondescription.py index e273d86..0773896 100644 --- a/tiramisu/option/syndynoptiondescription.py +++ b/tiramisu/option/syndynoptiondescription.py @@ -145,3 +145,16 @@ class SynDynLeadership(SynDynOptionDescription): await self._opt.pop(*args, followers=self.get_followers(), **kwargs) + + async def follower_force_store_value(self, + values, + value, + option_bag, + owner, + _commit) -> None: + await self._opt.follower_force_store_value(values, + value, + option_bag, + owner, + _commit, + dyn=self) diff --git a/tiramisu/setting.py b/tiramisu/setting.py index 83c0dad..b10f9cb 100644 --- a/tiramisu/setting.py +++ b/tiramisu/setting.py @@ -143,12 +143,12 @@ class OptionBag: def set_option(self, option, - path, index, config_bag): - if path is None: - path = option.impl_getpath() - self.path = path + if config_bag is undefined: + self.path = None + else: + self.path = option.impl_getpath() self.index = index self.option = option self.config_bag = config_bag @@ -646,12 +646,14 @@ class Settings(object): # validate properties async def calc_raises_properties(self, option_bag, - apply_requires=True): - if apply_requires and option_bag.properties_setted: + apply_requires=True, + uncalculated=False): + if not uncalculated and apply_requires and option_bag.properties_setted: option_properties = option_bag.properties else: option_properties = await self.getproperties(option_bag, - apply_requires=apply_requires) + apply_requires=apply_requires, + uncalculated=uncalculated) return self._calc_raises_properties(option_bag.config_bag.properties, option_bag.config_bag.permissives, option_properties) diff --git a/tiramisu/todict.py b/tiramisu/todict.py index 5e93257..c11d80b 100644 --- a/tiramisu/todict.py +++ b/tiramisu/todict.py @@ -206,7 +206,7 @@ class Requires(object): else: act = 'hide' inv_act = 'show' - if isinstance(option, ChoiceOption): + if option.get_type() == 'choice': require_option = self.tiramisu_web.config.unrestraint.option(option_path) values = await self.tiramisu_web.get_enum(require_option, await require_option.option.ismulti(), @@ -239,7 +239,7 @@ class Requires(object): #collect id of all options child = await childapi.option.get() if isinstance(child, SynDynOption): - child = child._impl_getopt() + child = child.opt self.options[child] = path current_action = None @@ -439,7 +439,7 @@ class TiramisuDict: child = await childapi_option.get() childtype = child.__class__.__name__ if childtype == 'SynDynOption': - childtype = child._impl_getopt().__class__.__name__ + childtype = child.opt.__class__.__name__ if await childapi_option.issymlinkoption(): web_type = 'symlink' value = None @@ -608,7 +608,8 @@ class TiramisuDict: settings = config.cfgimpl_get_settings() childapi._option_bag.config_bag.properties = await settings.get_context_properties(config._impl_properties_cache) childapi._option_bag.config_bag.properties -= {'permissive'} - properties = await childapi.property.get(only_raises=True) + properties = await childapi.property.get(only_raises=True, + uncalculated=True) properties -= await childapi.permissive.get() # 'hidden=True' means cannot access with or without permissive option # 'display=False' means cannot access only without permissive option diff --git a/tiramisu/value.py b/tiramisu/value.py index 5d3c2c0..7b8a382 100644 --- a/tiramisu/value.py +++ b/tiramisu/value.py @@ -616,13 +616,10 @@ class Values: settings = context.cfgimpl_get_settings() for option in await description.get_children(config_bag): name = option.impl_getname() - path = '.'.join(currpath + [name]) - if option.impl_is_optiondescription(): try: option_bag = OptionBag() option_bag.set_option(option, - path, None, od_config_bag) option_bag.properties = await settings.getproperties(option_bag) @@ -644,7 +641,6 @@ class Values: if not option.impl_is_follower(): option_bag = OptionBag() option_bag.set_option(option, - path, None, config_bag) option_bag.properties = await settings.getproperties(option_bag) @@ -655,7 +651,6 @@ class Values: for index in range(subconfig.cfgimpl_get_length()): option_bag = OptionBag() option_bag.set_option(option, - path, index, config_bag) option_bag.properties = await settings.getproperties(option_bag) @@ -664,7 +659,7 @@ class Values: option_bag) except PropertiesOptionError as err: if err.proptype in (['mandatory'], ['empty']): - yield path + yield option.impl_getpath() except ConfigError: pass