feat: reactive metaconfig
This commit is contained in:
parent
ac35f2428b
commit
47c413e60c
26 changed files with 3020 additions and 2932 deletions
|
|
@ -847,7 +847,7 @@ msgstr ""
|
|||
|
||||
#: tiramisu/option/option.py:294
|
||||
msgid "the value \"{}\" is not unique"
|
||||
msgstr "la valeur de \"{}\" n'est pas unique"
|
||||
msgstr "la valeur \"{}\" n'est pas unique"
|
||||
|
||||
#: tiramisu/option/option.py:356
|
||||
msgid "which must not be a list"
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"POT-Creation-Date: 2025-05-12 09:05+0200\n"
|
||||
"POT-Creation-Date: 2025-06-28 10:15+0300\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
|
|
@ -15,95 +15,95 @@ msgstr ""
|
|||
"Generated-By: pygettext.py 1.5\n"
|
||||
|
||||
|
||||
#: tiramisu/api.py:79
|
||||
#: tiramisu/api.py:86
|
||||
msgid "Settings:"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/api.py:83
|
||||
#: tiramisu/api.py:90
|
||||
msgid "Access to option without verifying permissive properties"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/api.py:88
|
||||
#: tiramisu/api.py:95
|
||||
msgid "Access to option without property restriction"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/api.py:93
|
||||
#: tiramisu/api.py:100
|
||||
msgid "Do not warnings during validation"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/api.py:97
|
||||
#: tiramisu/api.py:104
|
||||
msgid "Commands:"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/api.py:111 tiramisu/api.py:1857
|
||||
#: tiramisu/api.py:118 tiramisu/api.py:1920
|
||||
msgid "please specify a valid sub function ({0}.{1})"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/api.py:196
|
||||
#: tiramisu/api.py:206
|
||||
msgid "please do not specify index ({0}.{1})"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/api.py:201 tiramisu/api.py:856
|
||||
#: tiramisu/api.py:211 tiramisu/api.py:906
|
||||
msgid "please specify index with a follower option ({0}.{1})"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/api.py:222
|
||||
#: tiramisu/api.py:232
|
||||
msgid "please specify a valid sub function ({0}.{1}): {2}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/api.py:446
|
||||
#: tiramisu/api.py:493
|
||||
msgid "the option {0} is not a dynamic option, cannot get identifiers with only_self parameter to True"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/api.py:532
|
||||
#: tiramisu/api.py:581
|
||||
msgid "cannot get option from a follower symlink without index"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/api.py:607
|
||||
#: tiramisu/api.py:657
|
||||
msgid "cannot add this property: \"{0}\""
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/api.py:634
|
||||
#: tiramisu/api.py:684
|
||||
msgid "cannot remove option's property \"{0}\", use permissive instead in option \"{1}\""
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/api.py:638
|
||||
#: tiramisu/api.py:688
|
||||
msgid "cannot find \"{0}\" in option \"{1}\""
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/api.py:643
|
||||
#: tiramisu/api.py:693
|
||||
msgid "cannot remove option's property \"{0}\", use permissive instead in option \"{1}\" at index \"{2}\""
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/api.py:647
|
||||
#: tiramisu/api.py:697
|
||||
msgid "cannot find \"{0}\" in option \"{1}\" at index \"{2}\""
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/api.py:691
|
||||
#: tiramisu/api.py:741
|
||||
msgid "cannot find \"{0}\""
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/api.py:873
|
||||
#: tiramisu/api.py:923
|
||||
msgid "only multi value has defaultmulti"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/api.py:1037
|
||||
#: tiramisu/api.py:1087
|
||||
msgid "please specify a valid sub function ({0}.{1}) for {2}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/api.py:1424
|
||||
#: tiramisu/api.py:1485
|
||||
msgid "properties must be a frozenset"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/api.py:1428 tiramisu/api.py:1455
|
||||
#: tiramisu/api.py:1489 tiramisu/api.py:1516
|
||||
msgid "unknown when {} (must be in append or remove)"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/api.py:1441 tiramisu/api.py:1465 tiramisu/config.py:1676
|
||||
#: tiramisu/api.py:1502 tiramisu/api.py:1526 tiramisu/config.py:1722
|
||||
msgid "unknown type {}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/api.py:1829
|
||||
#: tiramisu/api.py:1892
|
||||
msgid "do not use unrestraint, nowarnings or forcepermissive together"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -207,79 +207,83 @@ msgstr ""
|
|||
msgid "unexpected error \"{1}\" in function \"{2}\" for option {0}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/config.py:574
|
||||
#: tiramisu/config.py:609
|
||||
msgid "there is no option description for this config (may be GroupConfig)"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/config.py:663
|
||||
#: tiramisu/config.py:698
|
||||
msgid "no option found in config with these criteria"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/config.py:978 tiramisu/option/optiondescription.py:74
|
||||
#: tiramisu/config.py:1024 tiramisu/option/optiondescription.py:74
|
||||
msgid "option description seems to be part of an other config"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/config.py:1140
|
||||
#: tiramisu/config.py:1186
|
||||
msgid "parent of {0} not already exists"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/config.py:1187
|
||||
#: tiramisu/config.py:1233
|
||||
msgid "cannot set leadership object has root optiondescription"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/config.py:1190
|
||||
#: tiramisu/config.py:1236
|
||||
msgid "cannot set dynoptiondescription object has root optiondescription"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/config.py:1242
|
||||
#: tiramisu/config.py:1282
|
||||
msgid "child must be a Config, GroupConfig, MixConfig or MetaConfig"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/config.py:1290
|
||||
msgid "config name must be uniq in groupconfig for \"{0}\""
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/config.py:1453
|
||||
#: tiramisu/config.py:1499
|
||||
msgid "unknown config \"{}\""
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/config.py:1478
|
||||
#: tiramisu/config.py:1524
|
||||
msgid "child must be a Config, MixConfig or MetaConfig"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/config.py:1513
|
||||
#: tiramisu/config.py:1559
|
||||
msgid "force_default, force_default_if_same or force_dont_change_value cannot be set with only_config"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/config.py:1523
|
||||
#: tiramisu/config.py:1569
|
||||
msgid "force_default and force_dont_change_value cannot be set together"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/config.py:1672
|
||||
#: tiramisu/config.py:1718
|
||||
msgid "config name must be uniq in groupconfig for {0}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/config.py:1717
|
||||
#: tiramisu/config.py:1763
|
||||
msgid "config added has no name, the name is mandatory"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/config.py:1722
|
||||
#: tiramisu/config.py:1768
|
||||
msgid "config name \"{0}\" is not uniq in groupconfig \"{1}\""
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/config.py:1740 tiramisu/config.py:1746
|
||||
#: tiramisu/config.py:1786 tiramisu/config.py:1792
|
||||
msgid "cannot find the config {0}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/config.py:1772
|
||||
#: tiramisu/config.py:1818
|
||||
msgid "MetaConfig with optiondescription must have string has child, not {}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/config.py:1784
|
||||
#: tiramisu/config.py:1830
|
||||
msgid "child must be a Config or MetaConfig"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/config.py:1789
|
||||
#: tiramisu/config.py:1835
|
||||
msgid "all config in metaconfig must have the same optiondescription"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/config.py:1806
|
||||
#: tiramisu/config.py:1852
|
||||
msgid "metaconfig must have the same optiondescription"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -391,23 +395,23 @@ msgstr ""
|
|||
msgid "the \"{0}\" function must not return a list (\"{1}\") for the follower option {2}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/error.py:331
|
||||
#: tiramisu/error.py:333
|
||||
msgid "invalid value"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/error.py:341
|
||||
#: tiramisu/error.py:343
|
||||
msgid "attention, \"{0}\" could be an invalid {1} for {2}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/error.py:345
|
||||
#: tiramisu/error.py:347
|
||||
msgid "attention, \"{0}\" could be an invalid {1} for {2} at index \"{3}\""
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/error.py:366 tiramisu/error.py:377
|
||||
#: tiramisu/error.py:368 tiramisu/error.py:379
|
||||
msgid "\"{0}\" is an invalid {1} for {2}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/error.py:368
|
||||
#: tiramisu/error.py:370
|
||||
msgid "\"{0}\" is an invalid {1} for {2} at index \"{3}\""
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -499,19 +503,19 @@ msgstr ""
|
|||
msgid "invalid string"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option/choiceoption.py:47
|
||||
#: tiramisu/option/choiceoption.py:52
|
||||
msgid "values must be a tuple or a calculation for {0}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option/choiceoption.py:70
|
||||
#: tiramisu/option/choiceoption.py:75
|
||||
msgid "the calculated values \"{0}\" for \"{1}\" is not a list"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option/choiceoption.py:101
|
||||
#: tiramisu/option/choiceoption.py:106
|
||||
msgid "only \"{0}\" is allowed"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option/choiceoption.py:103
|
||||
#: tiramisu/option/choiceoption.py:108
|
||||
msgid "only {0} are allowed"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -728,19 +732,19 @@ msgstr ""
|
|||
msgid "invalid default_multi value \"{0}\" for option {1}, must be a list for a submulti"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option/option.py:294
|
||||
#: tiramisu/option/option.py:291
|
||||
msgid "the value \"{}\" is not unique"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option/option.py:356
|
||||
#: tiramisu/option/option.py:353
|
||||
msgid "which must not be a list"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option/option.py:408 tiramisu/option/option.py:434
|
||||
#: tiramisu/option/option.py:408 tiramisu/option/option.py:446
|
||||
msgid "which must be a list"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option/option.py:428
|
||||
#: tiramisu/option/option.py:436
|
||||
msgid "which \"{}\" must be a list of list"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -805,27 +809,27 @@ msgstr ""
|
|||
msgid "too weak"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option/portoption.py:80
|
||||
#: tiramisu/option/portoption.py:77
|
||||
msgid "inconsistency in allowed range"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option/portoption.py:85
|
||||
#: tiramisu/option/portoption.py:82
|
||||
msgid "max value is empty"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option/portoption.py:98
|
||||
#: tiramisu/option/portoption.py:95
|
||||
msgid "range must have two values only"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option/portoption.py:101
|
||||
#: tiramisu/option/portoption.py:98
|
||||
msgid "first port in range must be smaller than the second one"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option/portoption.py:127
|
||||
#: tiramisu/option/portoption.py:124
|
||||
msgid "should be between {0} and {1}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option/portoption.py:129
|
||||
#: tiramisu/option/portoption.py:126
|
||||
msgid "must be between {0} and {1}"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -905,19 +909,15 @@ msgstr ""
|
|||
msgid "unknown action {}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/value.py:570 tiramisu/value.py:872
|
||||
#: tiramisu/value.py:557 tiramisu/value.py:859
|
||||
msgid "set owner \"{0}\" is forbidden"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/value.py:577
|
||||
#: tiramisu/value.py:564
|
||||
msgid "\"{0}\" is a default value, so we cannot change owner to \"{1}\""
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/value.py:751
|
||||
msgid "index {index} is greater than the length {length} for option {subconfig.option.impl_get_display_name(with_quote=True)}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/value.py:858
|
||||
#: tiramisu/value.py:845
|
||||
msgid "information's item not found \"{}\""
|
||||
msgstr ""
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
# from json import dumps, loads
|
||||
import asyncio
|
||||
from os import environ
|
||||
try:
|
||||
from tiramisu_api import Config
|
||||
|
|
@ -63,3 +62,14 @@ def parse_od_get(dico):
|
|||
else:
|
||||
ret[k.path()] = v
|
||||
return ret
|
||||
|
||||
|
||||
def get_dependencies(option):
|
||||
ret = []
|
||||
for a in option.dependencies():
|
||||
if a.isoptiondescription():
|
||||
ret.append((a.path(), None))
|
||||
else:
|
||||
ret.append((a.path(), a.index()))
|
||||
ret.sort()
|
||||
return ret
|
||||
|
|
|
|||
|
|
@ -191,7 +191,6 @@ def test_choiceoption_calc_opt_function_propertyerror():
|
|||
# assert not list_sessions()
|
||||
|
||||
|
||||
#def test_choiceoption_calc_opt_multi_function(config_type):
|
||||
def test_choiceoption_calc_opt_multi_function():
|
||||
# FIXME
|
||||
config_type = 'tiramisu'
|
||||
|
|
|
|||
|
|
@ -13,12 +13,6 @@ from tiramisu.error import PropertiesOptionError, ValueWarning, ConfigError
|
|||
import warnings
|
||||
|
||||
|
||||
#def teardown_function(function):
|
||||
# # test_od_not_list emit a warnings because of doesn't create a Config
|
||||
# with warnings.catch_warnings(record=True) as w:
|
||||
# assert list_sessions() == [], 'session list is not empty when leaving "{}"'.format(function.__name__)
|
||||
|
||||
|
||||
def make_description():
|
||||
gcoption = ChoiceOption('name', 'GC name', ('ref', 'framework'), 'ref')
|
||||
gcdummy = BoolOption('dummy', 'dummy', default=False)
|
||||
|
|
|
|||
|
|
@ -80,15 +80,15 @@ def test_copy_force_store_value():
|
|||
assert conf.value.exportation() == {'creole.general.wantref': {None: [True, 'user']}}
|
||||
assert conf2.value.exportation() == {'creole.general.wantref': {None: [False, 'forced']}}
|
||||
# assert not list_sessions()
|
||||
#
|
||||
#
|
||||
#def test_copy_force_store_value_metaconfig():
|
||||
# od1 = make_description()
|
||||
# meta = MetaConfig([], optiondescription=od1)
|
||||
# conf = meta.config.new()
|
||||
# assert meta.property.get() == conf.property.get()
|
||||
# assert meta.permissive.get() == conf.permissive.get()
|
||||
# conf.property.read_write()
|
||||
# assert conf.value.exportation() == {'creole.general.wantref': {None: [False, 'forced']}}
|
||||
# assert meta.value.exportation() == {}
|
||||
## assert not list_sessions()
|
||||
|
||||
|
||||
def test_copy_force_store_value_metaconfig():
|
||||
od1 = make_description()
|
||||
meta = MetaConfig([], optiondescription=od1)
|
||||
conf = meta.config.new()
|
||||
assert meta.property.get() == conf.property.get()
|
||||
assert meta.permissive.get() == conf.permissive.get()
|
||||
conf.property.read_write()
|
||||
assert conf.value.exportation() == {'creole.general.wantref': {None: [False, 'forced']}}
|
||||
assert meta.value.exportation() == {}
|
||||
# assert not list_sessions()
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# coding: utf-8
|
||||
from .autopath import do_autopath
|
||||
do_autopath()
|
||||
from .config import parse_od_get
|
||||
from .config import parse_od_get, get_dependencies
|
||||
import pytest
|
||||
|
||||
from tiramisu.setting import groups, owners
|
||||
|
|
@ -336,6 +336,7 @@ def test_prop_dyndescription_force_store_value_calculation_prefix():
|
|||
od2 = OptionDescription('od', '', [od])
|
||||
cfg = Config(od2)
|
||||
cfg.property.read_write()
|
||||
assert get_dependencies(cfg.option('od.lst')) == [('od.dodval1', None), ('od.dodval2', None)]
|
||||
assert cfg.option('od.dodval1.st').owner.isdefault() == False
|
||||
assert cfg.option('od.dodval2.st').owner.isdefault() == False
|
||||
assert parse_od_get(cfg.value.get()) == {'od.lst': ['val1', 'val2'], 'od.dodval1.st': 'val1', 'od.dodval2.st': 'val2'}
|
||||
|
|
@ -394,6 +395,8 @@ def test_callback_dyndescription_outside1():
|
|||
od = OptionDescription('od', '', [dod, out])
|
||||
od2 = OptionDescription('od', '', [od, lst])
|
||||
cfg = Config(od2)
|
||||
#
|
||||
assert get_dependencies(cfg.option('od.dodval1.st')) == [('od.out', None)]
|
||||
assert parse_od_get(cfg.value.get()) == {'od.dodval1.st': 'val', 'od.dodval2.st': 'val', 'od.out': 'val', 'lst': ['val1', 'val2']}
|
||||
cfg.option('od.dodval1.st').value.set('val1')
|
||||
cfg.option('od.dodval2.st').value.set('val2')
|
||||
|
|
@ -417,6 +420,8 @@ def test_callback_dyndescription_outside2():
|
|||
assert parse_od_get(cfg.value.get()) == {'od.dodval1.st': None, 'od.dodval2.st': None, 'od.out': None, 'lst': ['val1', 'val2']}
|
||||
cfg.option('od.out').value.set('val1')
|
||||
assert parse_od_get(cfg.value.get()) == {'od.dodval1.st': 'val1', 'od.dodval2.st': 'val1', 'od.out': 'val1', 'lst': ['val1', 'val2']}
|
||||
#
|
||||
assert get_dependencies(cfg.option('od.out')) == [('od.dodval1.st', None), ('od.dodval2.st', None)]
|
||||
# assert not list_sessions()
|
||||
|
||||
|
||||
|
|
@ -1191,6 +1196,8 @@ def test_leadership_dyndescription():
|
|||
cfg = Config(od1)
|
||||
owner = cfg.owner.get()
|
||||
#
|
||||
assert get_dependencies(cfg.option('od.stval1.st1.st2')) == [('od.stval1.st1', None)]
|
||||
assert get_dependencies(cfg.option('od.stval2.st1.st2')) == [('od.stval2.st1', None)]
|
||||
assert parse_od_get(cfg.value.get()) == {'od.stval2.st1.st1': [], 'od.stval1.st1.st1': []}
|
||||
assert cfg.option('od.stval1.st1.st1').value.get() == []
|
||||
assert cfg.option('od.stval2.st1.st1').value.get() == []
|
||||
|
|
@ -1250,6 +1257,9 @@ def test_leadership_dyndescription_force_store_value_leader():
|
|||
od1 = OptionDescription('od', '', [od])
|
||||
cfg = Config(od1)
|
||||
cfg.property.read_write()
|
||||
#
|
||||
assert get_dependencies(cfg.option('od.stval1.st1.st2')) == [('od.stval1.st1', None)]
|
||||
assert get_dependencies(cfg.option('od.stval2.st1.st2')) == [('od.stval2.st1', None)]
|
||||
assert cfg.option('od.stval1.st1.st1').owner.isdefault() == False
|
||||
assert cfg.option('od.stval2.st1.st1').owner.isdefault() == False
|
||||
assert cfg.option('od.stval1.st1.st2', 0).owner.isdefault() == True
|
||||
|
|
|
|||
|
|
@ -1055,7 +1055,7 @@ def test_follower_force_store_value_reset():
|
|||
# assert not list_sessions()
|
||||
|
||||
|
||||
#def test_follower_properties():
|
||||
def test_follower_properties():
|
||||
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=('aproperty',))
|
||||
interface1 = Leadership('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
|
||||
|
|
|
|||
|
|
@ -13,8 +13,6 @@ from tiramisu.error import PropertiesOptionError, ConfigError
|
|||
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
|
||||
|
||||
|
|
@ -688,25 +686,25 @@ def return_list(val=None, identifier=None):
|
|||
return ['val1', 'val2']
|
||||
|
||||
|
||||
#def test_mandatory_dyndescription():
|
||||
# st = StrOption('st', '', properties=('mandatory',))
|
||||
# dod = DynOptionDescription('dod', '', [st], identifiers=Calculation(return_list))
|
||||
# od = OptionDescription('od', '', [dod])
|
||||
# od2 = OptionDescription('od', '', [od])
|
||||
# cfg = Config(od2)
|
||||
# cfg.property.read_only()
|
||||
# compare(cfg.value.mandatory(), ['od.dodval1.st', 'od.dodval2.st'])
|
||||
#
|
||||
#
|
||||
#def test_mandatory_dyndescription_context():
|
||||
# val1 = StrOption('val1', '', ['val1', 'val2'], multi=True)
|
||||
# st = StrOption('st', '', properties=('mandatory',))
|
||||
# dod = DynOptionDescription('dod', '', [st], identifiers=Calculation(return_list, Params(ParamOption(val1))))
|
||||
# od = OptionDescription('od', '', [dod, val1])
|
||||
# od2 = OptionDescription('od', '', [od])
|
||||
# cfg = Config(od2)
|
||||
# cfg.property.read_only()
|
||||
# compare(cfg.value.mandatory(), ['od.dodval1.st', 'od.dodval2.st'])
|
||||
def test_mandatory_dyndescription():
|
||||
st = StrOption('st', '', properties=('mandatory',))
|
||||
dod = DynOptionDescription('dod', '', [st], identifiers=Calculation(return_list))
|
||||
od = OptionDescription('od', '', [dod])
|
||||
od2 = OptionDescription('od', '', [od])
|
||||
cfg = Config(od2)
|
||||
cfg.property.read_only()
|
||||
compare(cfg.value.mandatory(), ['od.dodval1.st', 'od.dodval2.st'])
|
||||
|
||||
|
||||
def test_mandatory_dyndescription_context():
|
||||
val1 = StrOption('val1', '', ['val1', 'val2'], multi=True)
|
||||
st = StrOption('st', '', properties=('mandatory',))
|
||||
dod = DynOptionDescription('dod', '', [st], identifiers=Calculation(return_list, Params(ParamOption(val1))))
|
||||
od = OptionDescription('od', '', [dod, val1])
|
||||
od2 = OptionDescription('od', '', [od])
|
||||
cfg = Config(od2)
|
||||
cfg.property.read_only()
|
||||
compare(cfg.value.mandatory(), ['od.dodval1.st', 'od.dodval2.st'])
|
||||
|
||||
|
||||
def test_mandatory_callback_leader_and_followers_leader():
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -15,76 +15,76 @@ def make_metaconfig():
|
|||
return MetaConfig([], optiondescription=od2, name='metacfg1')
|
||||
|
||||
|
||||
#def test_multi_parents_path():
|
||||
# """
|
||||
# metacfg1 (1) ---
|
||||
# | -- cfg1
|
||||
# metacfg2 (2) ---
|
||||
# """
|
||||
# metacfg1 = make_metaconfig()
|
||||
# cfg1 = metacfg1.config.new(type='config', name="cfg1")
|
||||
# metacfg2 = MetaConfig([cfg1], name='metacfg2')
|
||||
# #
|
||||
# assert metacfg1.config.path() == 'metacfg1'
|
||||
# assert metacfg2.config.path() == 'metacfg2'
|
||||
# assert cfg1.config.path() == 'metacfg2.metacfg1.cfg1'
|
||||
#
|
||||
#
|
||||
#def test_multi_parents_path_same():
|
||||
# """
|
||||
# --- metacfg2 (1) ---
|
||||
# metacfg1 --| | -- cfg1
|
||||
# --- metacfg3 (2) ---
|
||||
# """
|
||||
# metacfg1 = make_metaconfig()
|
||||
# metacfg2 = metacfg1.config.new(type='metaconfig', name="metacfg2")
|
||||
# metacfg3 = metacfg1.config.new(type='metaconfig', name="metacfg3")
|
||||
# cfg1 = metacfg2.config.new(type='config', name="cfg1")
|
||||
# metacfg3.config.add(cfg1)
|
||||
# #
|
||||
# assert metacfg2.config.path() == 'metacfg1.metacfg2'
|
||||
# assert metacfg3.config.path() == 'metacfg1.metacfg3'
|
||||
# assert cfg1.config.path() == 'metacfg1.metacfg3.metacfg1.metacfg2.cfg1'
|
||||
# metacfg1.option('od1.i1').value.set(1)
|
||||
# metacfg3.option('od1.i1').value.set(2)
|
||||
# assert cfg1.option('od1.i1').value.get() == 1
|
||||
# orideep = cfg1.config.deepcopy(metaconfig_prefix="test_", name='test_cfg1')
|
||||
# deep = orideep
|
||||
# while True:
|
||||
# try:
|
||||
# children = list(deep.config.list())
|
||||
# except:
|
||||
# break
|
||||
# assert len(children) < 2
|
||||
# deep = children[0]
|
||||
# assert deep.config.path() == 'test_metacfg3.test_metacfg1.test_metacfg2.test_cfg1'
|
||||
# assert cfg1.option('od1.i1').value.get() == 1
|
||||
#
|
||||
#
|
||||
#
|
||||
#def test_multi_parents_value():
|
||||
# metacfg1 = make_metaconfig()
|
||||
# cfg1 = metacfg1.config.new(type='config', name="cfg1")
|
||||
# metacfg2 = MetaConfig([cfg1], name='metacfg2')
|
||||
# #
|
||||
# assert cfg1.option('od1.i1').value.get() == None
|
||||
# assert cfg1.option('od1.i2').value.get() == 1
|
||||
# assert cfg1.option('od1.i3').value.get() == None
|
||||
# #
|
||||
# assert metacfg1.option('od1.i1').value.get() == None
|
||||
# assert metacfg1.option('od1.i2').value.get() == 1
|
||||
# assert metacfg1.option('od1.i3').value.get() == None
|
||||
# #
|
||||
# assert metacfg2.option('od1.i1').value.get() == None
|
||||
# assert metacfg2.option('od1.i2').value.get() == 1
|
||||
# assert metacfg2.option('od1.i3').value.get() == None
|
||||
# #
|
||||
# metacfg1.option('od1.i3').value.set(3)
|
||||
# assert metacfg1.option('od1.i3').value.get() == 3
|
||||
# assert cfg1.option('od1.i3').value.get() == 3
|
||||
# assert metacfg2.option('od1.i2').value.get() == 1
|
||||
# #
|
||||
# metacfg2.option('od1.i2').value.set(4)
|
||||
# assert metacfg2.option('od1.i2').value.get() == 4
|
||||
# assert metacfg1.option('od1.i2').value.get() == 1
|
||||
# assert cfg1.option('od1.i2').value.get() == 4
|
||||
def test_multi_parents_path():
|
||||
"""
|
||||
metacfg1 (1) ---
|
||||
| -- cfg1
|
||||
metacfg2 (2) ---
|
||||
"""
|
||||
metacfg1 = make_metaconfig()
|
||||
cfg1 = metacfg1.config.new(type='config', name="cfg1")
|
||||
metacfg2 = MetaConfig([cfg1], name='metacfg2')
|
||||
#
|
||||
assert metacfg1.config.path() == 'metacfg1'
|
||||
assert metacfg2.config.path() == 'metacfg2'
|
||||
assert cfg1.config.path() == 'metacfg2.metacfg1.cfg1'
|
||||
|
||||
|
||||
def test_multi_parents_path_same():
|
||||
"""
|
||||
--- metacfg2 (1) ---
|
||||
metacfg1 --| | -- cfg1
|
||||
--- metacfg3 (2) ---
|
||||
"""
|
||||
metacfg1 = make_metaconfig()
|
||||
metacfg2 = metacfg1.config.new(type='metaconfig', name="metacfg2")
|
||||
metacfg3 = metacfg1.config.new(type='metaconfig', name="metacfg3")
|
||||
cfg1 = metacfg2.config.new(type='config', name="cfg1")
|
||||
metacfg3.config.add(cfg1)
|
||||
#
|
||||
assert metacfg2.config.path() == 'metacfg1.metacfg2'
|
||||
assert metacfg3.config.path() == 'metacfg1.metacfg3'
|
||||
assert cfg1.config.path() == 'metacfg1.metacfg3.metacfg1.metacfg2.cfg1'
|
||||
metacfg1.option('od1.i1').value.set(1)
|
||||
metacfg3.option('od1.i1').value.set(2)
|
||||
assert cfg1.option('od1.i1').value.get() == 1
|
||||
orideep = cfg1.config.deepcopy(metaconfig_prefix="test_", name='test_cfg1')
|
||||
deep = orideep
|
||||
while True:
|
||||
try:
|
||||
children = list(deep.config.list())
|
||||
except:
|
||||
break
|
||||
assert len(children) < 2
|
||||
deep = children[0]
|
||||
assert deep.config.path() == 'test_metacfg3.test_metacfg1.test_metacfg2.test_cfg1'
|
||||
assert cfg1.option('od1.i1').value.get() == 1
|
||||
|
||||
|
||||
|
||||
def test_multi_parents_value():
|
||||
metacfg1 = make_metaconfig()
|
||||
cfg1 = metacfg1.config.new(type='config', name="cfg1")
|
||||
metacfg2 = MetaConfig([cfg1], name='metacfg2')
|
||||
#
|
||||
assert cfg1.option('od1.i1').value.get() == None
|
||||
assert cfg1.option('od1.i2').value.get() == 1
|
||||
assert cfg1.option('od1.i3').value.get() == None
|
||||
#
|
||||
assert metacfg1.option('od1.i1').value.get() == None
|
||||
assert metacfg1.option('od1.i2').value.get() == 1
|
||||
assert metacfg1.option('od1.i3').value.get() == None
|
||||
#
|
||||
assert metacfg2.option('od1.i1').value.get() == None
|
||||
assert metacfg2.option('od1.i2').value.get() == 1
|
||||
assert metacfg2.option('od1.i3').value.get() == None
|
||||
#
|
||||
metacfg1.option('od1.i3').value.set(3)
|
||||
assert metacfg1.option('od1.i3').value.get() == 3
|
||||
assert cfg1.option('od1.i3').value.get() == 3
|
||||
assert metacfg2.option('od1.i2').value.get() == 1
|
||||
#
|
||||
metacfg2.option('od1.i2').value.set(4)
|
||||
assert metacfg2.option('od1.i2').value.get() == 4
|
||||
assert metacfg1.option('od1.i2').value.get() == 1
|
||||
assert cfg1.option('od1.i2').value.get() == 4
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ from tiramisu import ChoiceOption, BoolOption, IntOption, FloatOption, \
|
|||
valid_ip_netmask, ParamSelfOption, ParamInformation, ParamSelfInformation
|
||||
from tiramisu.error import PropertiesOptionError, ConflictError, LeadershipError, ConfigError
|
||||
from tiramisu.i18n import _
|
||||
from .config import config_type, get_config, parse_od_get
|
||||
from .config import config_type, get_config, parse_od_get, get_dependencies
|
||||
|
||||
|
||||
def return_val():
|
||||
|
|
@ -693,6 +693,7 @@ def test_callback_leader_and_followers_leader(config_type):
|
|||
cfg = Config(od1)
|
||||
cfg.property.read_write()
|
||||
cfg = get_config(cfg, config_type)
|
||||
assert [(a.path(), a.index()) for a in cfg.option('val1').dependencies()] == [('val2.val2', None)]
|
||||
assert cfg.option('val1').value.get() == ['val']
|
||||
assert cfg.option('val2.val2').value.get() == ['val']
|
||||
#
|
||||
|
|
@ -783,10 +784,29 @@ def test_callback_leader_and_followers_leader2(config_type):
|
|||
cfg = Config(od1)
|
||||
cfg.property.read_write()
|
||||
cfg = get_config(cfg, config_type)
|
||||
assert get_dependencies(cfg.option('val1.val2')) == [('val1', None)]
|
||||
assert get_dependencies(cfg.option('val1.val3')) == [('val1', None)] #, ('val2.val2', 0)]
|
||||
assert get_dependencies(cfg.option('val1.val4')) == [('val1', None)] #, ('val2.val3', 0)]
|
||||
#
|
||||
cfg.option('val1.val1').value.set(['val'])
|
||||
assert get_dependencies(cfg.option('val1.val2')) == [('val1', None), ('val1.val3', 0)]
|
||||
assert get_dependencies(cfg.option('val1.val2', 0)) == [('val1', None), ('val1.val3', 0)]
|
||||
assert get_dependencies(cfg.option('val1.val3')) == [('val1', None), ('val1.val4', 0)]
|
||||
assert get_dependencies(cfg.option('val1.val3', 0)) == [('val1', None), ('val1.val4', 0)]
|
||||
assert get_dependencies(cfg.option('val1.val4')) == [('val1', None)]
|
||||
|
||||
assert cfg.option('val1.val4', 0).value.get() == 'val2'
|
||||
assert cfg.option('val1.val3', 0).value.get() == 'val2'
|
||||
assert cfg.option('val1.val2', 0).value.get() == 'val2'
|
||||
#
|
||||
cfg.option('val1.val1').value.set(['val1', 'val2'])
|
||||
assert get_dependencies(cfg.option('val1.val2')) == [('val1', None), ('val1.val3', 0), ('val1.val3', 1)]
|
||||
assert get_dependencies(cfg.option('val1.val2', 0)) == [('val1', None), ('val1.val3', 0)]
|
||||
assert get_dependencies(cfg.option('val1.val2', 1)) == [('val1', None), ('val1.val3', 1)]
|
||||
assert get_dependencies(cfg.option('val1.val3')) == [('val1', None), ('val1.val4', 0), ('val1.val4', 1)]
|
||||
assert get_dependencies(cfg.option('val1.val3', 0)) == [('val1', None), ('val1.val4', 0)]
|
||||
assert get_dependencies(cfg.option('val1.val3', 1)) == [('val1', None), ('val1.val4', 1)]
|
||||
assert get_dependencies(cfg.option('val1.val4')) == [('val1', None)]
|
||||
# assert not list_sessions()
|
||||
|
||||
|
||||
|
|
@ -1499,6 +1519,7 @@ def test_leadership_callback_description(config_type):
|
|||
cfg.option('od.st.st1.st2', 0).value.set('yes')
|
||||
assert cfg.option('od.st.st1.st1').owner.get() == owner
|
||||
assert cfg.option('od.st.st1.st2', 0).owner.get() == owner
|
||||
assert get_dependencies(cfg.option('od.st.st1.st2')) == [('od.st.st1', None)]
|
||||
# assert not list_sessions()
|
||||
|
||||
|
||||
|
|
@ -1515,6 +1536,8 @@ def test_leadership_callback_outside(config_type):
|
|||
owner = cfg.owner.get()
|
||||
cfg.option('od.st.st1.st1').value.set(['yes'])
|
||||
assert parse_od_get(cfg.value.get()) == {'od.st.st1.st1': [{'od.st.st1.st1': 'yes', 'od.st.st1.st2': 'val2'}], 'od.st.st3': ['val2']}
|
||||
assert get_dependencies(cfg.option('od.st.st1.st2')) == [('od.st.st1', None), ('od.st.st3', None,)]
|
||||
|
||||
## assert not list_sessions()
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -154,8 +154,8 @@ def test_force_default_on_freeze_multi():
|
|||
# with pytest.raises(ConfigError):
|
||||
# Config(od1)
|
||||
# assert not list_sessions()
|
||||
|
||||
|
||||
#
|
||||
#
|
||||
#def test_force_metaconfig_on_freeze_leader():
|
||||
# dummy1 = BoolOption('dummy1', 'Test int option', multi=True, properties=('force_metaconfig_on_freeze',))
|
||||
# dummy2 = BoolOption('dummy2', 'Test string option', multi=True)
|
||||
|
|
|
|||
|
|
@ -818,27 +818,27 @@ def test_reset_properties_force_store_value():
|
|||
# assert not list_sessions()
|
||||
|
||||
|
||||
#def test_importation_force_store_value():
|
||||
# gcdummy = BoolOption('dummy', 'dummy', default=False,
|
||||
# properties=('force_store_value',))
|
||||
# gcgroup = OptionDescription('gc', '', [gcdummy])
|
||||
# od1 = OptionDescription('tiramisu', '', [gcgroup])
|
||||
# config1 = Config(od1)
|
||||
# assert config1.value.exportation() == {}
|
||||
# config1.property.add('frozen')
|
||||
# assert config1.value.exportation() == {}
|
||||
# config1.property.add('force_store_value')
|
||||
# assert config1.value.exportation() == {'gc.dummy': {None: [False, 'forced']}}
|
||||
# exportation = config1.property.exportation()
|
||||
# config2 = Config(od1)
|
||||
# assert config2.value.exportation() == {}
|
||||
# config2.property.importation(exportation)
|
||||
# assert config2.value.exportation() == {'gc.dummy': {None: [False, 'forced']}}
|
||||
# config2.property.importation(exportation)
|
||||
# assert config2.value.exportation() == {'gc.dummy': {None: [False, 'forced']}}
|
||||
## assert not list_sessions()
|
||||
#
|
||||
#
|
||||
def test_importation_force_store_value():
|
||||
gcdummy = BoolOption('dummy', 'dummy', default=False,
|
||||
properties=('force_store_value',))
|
||||
gcgroup = OptionDescription('gc', '', [gcdummy])
|
||||
od1 = OptionDescription('tiramisu', '', [gcgroup])
|
||||
config1 = Config(od1)
|
||||
assert config1.value.exportation() == {}
|
||||
config1.property.add('frozen')
|
||||
assert config1.value.exportation() == {}
|
||||
config1.property.add('force_store_value')
|
||||
assert config1.value.exportation() == {'gc.dummy': {None: [False, 'forced']}}
|
||||
exportation = config1.property.exportation()
|
||||
config2 = Config(od1)
|
||||
assert config2.value.exportation() == {}
|
||||
config2.property.importation(exportation)
|
||||
assert config2.value.exportation() == {'gc.dummy': {None: [False, 'forced']}}
|
||||
config2.property.importation(exportation)
|
||||
assert config2.value.exportation() == {'gc.dummy': {None: [False, 'forced']}}
|
||||
# assert not list_sessions()
|
||||
|
||||
|
||||
def test_set_modified_value():
|
||||
gcdummy = BoolOption('dummy', 'dummy', default=False, properties=('force_store_value',))
|
||||
gcgroup = OptionDescription('gc', '', [gcdummy])
|
||||
|
|
@ -920,18 +920,18 @@ def test_set_modified_value():
|
|||
# assert not list_sessions()
|
||||
|
||||
|
||||
#def test_none_is_not_modified():
|
||||
# gcdummy = StrOption('dummy', 'dummy', properties=('force_store_value',))
|
||||
# gcdummy1 = StrOption('dummy1', 'dummy1', default="str", properties=('force_store_value',))
|
||||
# gcgroup = OptionDescription('gc', '', [gcdummy, gcdummy1])
|
||||
# od1 = OptionDescription('tiramisu', '', [gcgroup])
|
||||
# cfg = Config(od1)
|
||||
# assert cfg.value.exportation() == {}
|
||||
# cfg.property.read_write()
|
||||
# assert cfg.value.exportation() == {'gc.dummy1': {None: ['str', 'forced']}}
|
||||
## assert not list_sessions()
|
||||
#
|
||||
#
|
||||
def test_none_is_not_modified():
|
||||
gcdummy = StrOption('dummy', 'dummy', properties=('force_store_value',))
|
||||
gcdummy1 = StrOption('dummy1', 'dummy1', default="str", properties=('force_store_value',))
|
||||
gcgroup = OptionDescription('gc', '', [gcdummy, gcdummy1])
|
||||
od1 = OptionDescription('tiramisu', '', [gcgroup])
|
||||
cfg = Config(od1)
|
||||
assert cfg.value.exportation() == {}
|
||||
cfg.property.read_write()
|
||||
assert cfg.value.exportation() == {'gc.dummy1': {None: ['str', 'forced']}}
|
||||
# assert not list_sessions()
|
||||
|
||||
|
||||
def test_pprint():
|
||||
msg_error = _("cannot access to {0} {1} because has {2} {3}")
|
||||
msg_is_not = _('the value of "{0}" is not {1}')
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ def return_val(value, param=None):
|
|||
|
||||
|
||||
def return_if_val(value):
|
||||
if value != 'val':
|
||||
if value not in ['val', 'val_not_raise']:
|
||||
raise ValueError('test error')
|
||||
|
||||
|
||||
|
|
@ -341,6 +341,13 @@ def test_validator_multi(config_type):
|
|||
with warnings.catch_warnings(record=True) as w:
|
||||
cfg.option('opt1').value.set(['val', 'val1'])
|
||||
assert len(w) == 1
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
cfg.option('opt1').value.set(['val1', 'val2'])
|
||||
assert len(w) == 2
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
# same value twice
|
||||
cfg.option('opt1').value.set(['val', 'val', 'val_not_raise'])
|
||||
assert len(w) == 2
|
||||
# assert not list_sessions()
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -146,8 +146,8 @@ def test_slots_option_readonly():
|
|||
with pytest.raises(AttributeError):
|
||||
q._requires = 'q'
|
||||
# assert not list_sessions()
|
||||
|
||||
|
||||
#
|
||||
#
|
||||
#def test_slots_description():
|
||||
# # __slots__ for OptionDescription should be complete for __getattr__
|
||||
# slots = set()
|
||||
|
|
|
|||
|
|
@ -528,43 +528,43 @@ def test_submulti_unique():
|
|||
# assert not list_sessions()
|
||||
|
||||
|
||||
#def test_multi_submulti_meta():
|
||||
# multi = StrOption('multi', '', multi=submulti)
|
||||
# od1 = OptionDescription('od', '', [multi])
|
||||
# cfg = Config(od1, name='cfg')
|
||||
# cfg.property.read_write()
|
||||
# cfg2 = Config(od1)
|
||||
# cfg2.property.read_write()
|
||||
# meta = MetaConfig([cfg, cfg2])
|
||||
# meta.property.read_write()
|
||||
# meta.option('multi').value.set([['val']])
|
||||
# assert meta.option('multi').value.get() == [['val']]
|
||||
# newcfg = meta.config('cfg')
|
||||
# newcfg.option('multi').value.set([['val', None]])
|
||||
# assert cfg.option('multi').value.get() == [['val', None]]
|
||||
# newcfg = meta.config('cfg')
|
||||
# assert newcfg.option('multi').value.get() == [['val', None]]
|
||||
# assert meta.option('multi').value.get() == [['val']]
|
||||
## assert not list_sessions()
|
||||
#
|
||||
#
|
||||
#def test_multi_submulti_meta_no_cache():
|
||||
# multi = StrOption('multi', '', multi=submulti)
|
||||
# multi = StrOption('multi', '', multi=submulti)
|
||||
# od1 = OptionDescription('od', '', [multi])
|
||||
# cfg = Config(od1, name='cfg')
|
||||
# cfg.property.read_write()
|
||||
# cfg2 = Config(od1)
|
||||
# cfg.property.read_write()
|
||||
# meta = MetaConfig([cfg, cfg2])
|
||||
# meta.property.read_write()
|
||||
# meta.property.remove('cache')
|
||||
# meta.option('multi').value.set([['val']])
|
||||
# assert meta.option('multi').value.get() == [['val']]
|
||||
# newcfg = meta.config('cfg')
|
||||
# newcfg.option('multi').value.set([['val', None]])
|
||||
# assert cfg.option('multi').value.get() == [['val', None]]
|
||||
# newcfg = meta.config('cfg')
|
||||
# assert newcfg.option('multi').value.get() == [['val', None]]
|
||||
# assert meta.option('multi').value.get() == [['val']]
|
||||
## assert not list_sessions()
|
||||
def test_multi_submulti_meta():
|
||||
multi = StrOption('multi', '', multi=submulti)
|
||||
od1 = OptionDescription('od', '', [multi])
|
||||
cfg = Config(od1, name='cfg')
|
||||
cfg.property.read_write()
|
||||
cfg2 = Config(od1)
|
||||
cfg2.property.read_write()
|
||||
meta = MetaConfig([cfg, cfg2])
|
||||
meta.property.read_write()
|
||||
meta.option('multi').value.set([['val']])
|
||||
assert meta.option('multi').value.get() == [['val']]
|
||||
newcfg = meta.config('cfg')
|
||||
newcfg.option('multi').value.set([['val', None]])
|
||||
assert cfg.option('multi').value.get() == [['val', None]]
|
||||
newcfg = meta.config('cfg')
|
||||
assert newcfg.option('multi').value.get() == [['val', None]]
|
||||
assert meta.option('multi').value.get() == [['val']]
|
||||
# assert not list_sessions()
|
||||
|
||||
|
||||
def test_multi_submulti_meta_no_cache():
|
||||
multi = StrOption('multi', '', multi=submulti)
|
||||
multi = StrOption('multi', '', multi=submulti)
|
||||
od1 = OptionDescription('od', '', [multi])
|
||||
cfg = Config(od1, name='cfg')
|
||||
cfg.property.read_write()
|
||||
cfg2 = Config(od1)
|
||||
cfg.property.read_write()
|
||||
meta = MetaConfig([cfg, cfg2])
|
||||
meta.property.read_write()
|
||||
meta.property.remove('cache')
|
||||
meta.option('multi').value.set([['val']])
|
||||
assert meta.option('multi').value.get() == [['val']]
|
||||
newcfg = meta.config('cfg')
|
||||
newcfg.option('multi').value.set([['val', None]])
|
||||
assert cfg.option('multi').value.get() == [['val', None]]
|
||||
newcfg = meta.config('cfg')
|
||||
assert newcfg.option('multi').value.get() == [['val', None]]
|
||||
assert meta.option('multi').value.get() == [['val']]
|
||||
# assert not list_sessions()
|
||||
|
|
|
|||
152
tiramisu/api.py
152
tiramisu/api.py
|
|
@ -1,5 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (C) 2017-2024 Team tiramisu (see AUTHORS for all contributors)
|
||||
# Copyright (C) 2017-2025 Team tiramisu (see AUTHORS for all contributors)
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Lesser General Public License as published by the
|
||||
|
|
@ -52,6 +52,13 @@ from .autolib import Calculation
|
|||
TIRAMISU_VERSION = 5
|
||||
|
||||
|
||||
class Fake_SubConfig:
|
||||
def __init__(self, config_bag, path, index):
|
||||
self.config_bag = config_bag
|
||||
self.path = path
|
||||
self.index = index
|
||||
|
||||
|
||||
class TiramisuHelp:
|
||||
_tmpl_help = " {0}\t{1}"
|
||||
|
||||
|
|
@ -120,13 +127,16 @@ class CommonTiramisu(TiramisuHelp):
|
|||
|
||||
def _set_subconfig(self) -> None:
|
||||
if not self._subconfig:
|
||||
self._subconfig = self._config_bag.context.get_sub_config(
|
||||
self._config_bag,
|
||||
self._path,
|
||||
self._index,
|
||||
validate_properties=False,
|
||||
allow_dynoption=self._allow_dynoption,
|
||||
)
|
||||
try:
|
||||
self._subconfig = self._config_bag.context.get_sub_config(
|
||||
self._config_bag,
|
||||
self._path,
|
||||
self._index,
|
||||
validate_properties=False,
|
||||
allow_dynoption=self._allow_dynoption,
|
||||
)
|
||||
except AssertionError as err:
|
||||
raise ConfigError(str(err))
|
||||
|
||||
|
||||
def option_type(typ):
|
||||
|
|
@ -202,7 +212,7 @@ def option_type(typ):
|
|||
"please specify index with a follower option ({0}.{1})"
|
||||
).format(self.__class__.__name__, func.__name__)
|
||||
raise ConfigError(msg)
|
||||
if self._validate_properties and "dont_validate_property" not in types:
|
||||
if 'validate_properties' in types or (self._validate_properties and "dont_validate_property" not in types):
|
||||
settings = self._config_bag.context.get_settings()
|
||||
parent = self._subconfig.parent
|
||||
if parent and parent.transitive_properties:
|
||||
|
|
@ -253,10 +263,11 @@ class _TiramisuOptionWalk:
|
|||
validate_properties: bool,
|
||||
*,
|
||||
uncalculated: bool = False,
|
||||
with_index: bool = True,
|
||||
):
|
||||
options = []
|
||||
for sub_subconfig in subconfig.get_children(
|
||||
validate_properties, uncalculated=uncalculated
|
||||
validate_properties, uncalculated=uncalculated, with_index=with_index,
|
||||
):
|
||||
options.append(
|
||||
TiramisuOption(
|
||||
|
|
@ -287,7 +298,7 @@ class _TiramisuOptionOptionDescription:
|
|||
"""Get Tiramisu option"""
|
||||
return self._subconfig.option
|
||||
|
||||
@option_type(["optiondescription", "option", "with_or_without_index", "symlink"])
|
||||
@option_type(["optiondescription", "option", "with_or_without_index", "symlink", "allow_dynoption"])
|
||||
def isoptiondescription(self):
|
||||
"""Test if option is an optiondescription"""
|
||||
return self._subconfig.option.impl_is_optiondescription()
|
||||
|
|
@ -336,6 +347,15 @@ class _TiramisuOptionOptionDescription:
|
|||
return self._subconfig.option.impl_getpath()
|
||||
return self._subconfig.true_path
|
||||
|
||||
def parent(self):
|
||||
parent = self._subconfig.parent
|
||||
return TiramisuOption(
|
||||
parent.path,
|
||||
None,
|
||||
self._config_bag,
|
||||
subconfig=parent,
|
||||
)
|
||||
|
||||
@option_type(["optiondescription", "option", "symlink", "with_or_without_index"])
|
||||
def has_dependency(
|
||||
self,
|
||||
|
|
@ -345,18 +365,54 @@ class _TiramisuOptionOptionDescription:
|
|||
return self._subconfig.option.impl_has_dependency(self_is_dep)
|
||||
|
||||
@option_type(["optiondescription", "option", "symlink", "with_or_without_index"])
|
||||
def dependencies(self):
|
||||
def dependencies(
|
||||
self,
|
||||
*,
|
||||
uncalculated: bool = False,
|
||||
):
|
||||
"""Get dependencies from this option"""
|
||||
options = []
|
||||
for option in self._subconfig.option.get_dependencies(self._config_bag.context):
|
||||
options.append(
|
||||
TiramisuOption(
|
||||
option().impl_getpath(),
|
||||
None,
|
||||
self._config_bag,
|
||||
allow_dynoption=True,
|
||||
)
|
||||
)
|
||||
context = self._config_bag.context
|
||||
index = self._index
|
||||
parent = self._subconfig.parent
|
||||
parent_option = parent.option
|
||||
for woption in self._subconfig.option.get_dependencies(self._config_bag.context):
|
||||
option = woption()
|
||||
if not uncalculated and option.issubdyn():
|
||||
for subconfig in context.get_dynamic_from_dyn_option(self._subconfig, option):
|
||||
options.append(
|
||||
TiramisuOption(
|
||||
subconfig.path,
|
||||
None,
|
||||
self._config_bag,
|
||||
)
|
||||
)
|
||||
elif not uncalculated and option.impl_is_dynoptiondescription():
|
||||
for subconfig in context.get_dynamic_from_dyn_option(self._subconfig, option):
|
||||
options.append(
|
||||
TiramisuOption(
|
||||
subconfig.path,
|
||||
None,
|
||||
self._config_bag,
|
||||
)
|
||||
)
|
||||
else:
|
||||
if not option.impl_is_optiondescription() and option.impl_is_follower() and parent_option.impl_is_leadership() and parent_option.in_same_leadership(option):
|
||||
if index is not None:
|
||||
current_indexes = [index]
|
||||
else:
|
||||
current_indexes = range(parent.get_length_leadership())
|
||||
else:
|
||||
current_indexes = [None]
|
||||
for current_index in current_indexes:
|
||||
options.append(
|
||||
TiramisuOption(
|
||||
option.impl_getpath(),
|
||||
current_index,
|
||||
self._config_bag,
|
||||
allow_dynoption=uncalculated,
|
||||
)
|
||||
)
|
||||
return options
|
||||
|
||||
@option_type(["option", "optiondescription", "symlink", "with_or_without_index"])
|
||||
|
|
@ -456,27 +512,27 @@ class _TiramisuOptionOptionDescription:
|
|||
class _TiramisuOptionOption(_TiramisuOptionOptionDescription):
|
||||
"""Manage option"""
|
||||
|
||||
@option_type(["option", "symlink", "with_or_without_index"])
|
||||
@option_type(["option", "symlink", "with_or_without_index", "allow_dynoption"])
|
||||
def ismulti(self):
|
||||
"""Test if option could have multi value"""
|
||||
return self._subconfig.option.impl_is_multi()
|
||||
|
||||
@option_type(["option", "symlink", "with_or_without_index"])
|
||||
@option_type(["option", "symlink", "with_or_without_index", "allow_dynoption"])
|
||||
def issubmulti(self):
|
||||
"""Test if option could have submulti value"""
|
||||
return self._subconfig.option.impl_is_submulti()
|
||||
|
||||
@option_type(["option", "with_or_without_index", "symlink"])
|
||||
@option_type(["option", "with_or_without_index", "symlink", "allow_dynoption"])
|
||||
def isleader(self):
|
||||
"""Test if option is a leader"""
|
||||
return self._subconfig.option.impl_is_leader()
|
||||
|
||||
@option_type(["option", "with_or_without_index", "symlink"])
|
||||
@option_type(["option", "with_or_without_index", "symlink", "allow_dynoption"])
|
||||
def isfollower(self):
|
||||
"""Test if option is a follower"""
|
||||
return self._subconfig.option.impl_is_follower()
|
||||
|
||||
@option_type(["option", "symlink", "with_or_without_index"])
|
||||
@option_type(["option", "symlink", "with_or_without_index", "allow_dynoption"])
|
||||
def issymlinkoption(self) -> bool:
|
||||
"""Test if option is a symlink option"""
|
||||
return self._subconfig.option.impl_is_symlinkoption()
|
||||
|
|
@ -498,9 +554,11 @@ class _TiramisuOptionOption(_TiramisuOptionOptionDescription):
|
|||
return r"^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$"
|
||||
|
||||
@option_type(["option", "with_or_without_index", "symlink"])
|
||||
def index(self):
|
||||
def index(self, index=None):
|
||||
"""Get index of option"""
|
||||
return self._subconfig.index
|
||||
if index is None:
|
||||
return self._subconfig.index
|
||||
return TiramisuOption(self._path, index, self._config_bag)
|
||||
|
||||
@option_type(["symlink", "optiondescription"])
|
||||
def option(self, *args, **kwargs):
|
||||
|
|
@ -546,9 +604,9 @@ class TiramisuOptionOwner(CommonTiramisuOption):
|
|||
_validate_properties = True
|
||||
|
||||
@option_type(["symlink", "option", "with_index"])
|
||||
def get(self):
|
||||
def get(self, only_self=False):
|
||||
"""Get owner for a specified option"""
|
||||
return self._config_bag.context.get_owner(self._subconfig)
|
||||
return self._config_bag.context.get_owner(self._subconfig, validate_meta=not only_self)
|
||||
|
||||
@option_type(["symlink", "option", "with_index"])
|
||||
def isdefault(self):
|
||||
|
|
@ -597,6 +655,7 @@ class TiramisuOptionProperty(CommonTiramisuOption):
|
|||
self._subconfig,
|
||||
uncalculated=uncalculated,
|
||||
apply_requires=apply_requires,
|
||||
not_unrestraint=True,
|
||||
)
|
||||
|
||||
@option_type(["option", "optiondescription", "with_or_without_index"])
|
||||
|
|
@ -1056,12 +1115,13 @@ class TiramisuOption(
|
|||
self._set_subconfig()
|
||||
return self._subconfig.option.impl_get_group_type()
|
||||
|
||||
@option_type("optiondescription")
|
||||
@option_type(["optiondescription", "validate_properties"])
|
||||
def list(
|
||||
self,
|
||||
*,
|
||||
validate_properties: bool = True,
|
||||
uncalculated: bool = False,
|
||||
with_index: bool = True,
|
||||
):
|
||||
"""List options inside an option description (by default list only option)"""
|
||||
self._set_subconfig()
|
||||
|
|
@ -1069,6 +1129,7 @@ class TiramisuOption(
|
|||
self._subconfig,
|
||||
validate_properties,
|
||||
uncalculated=uncalculated,
|
||||
with_index=with_index,
|
||||
)
|
||||
|
||||
def _load_dict(
|
||||
|
|
@ -1189,6 +1250,8 @@ class TiramisuContextValue(TiramisuConfig, _TiramisuODGet):
|
|||
self,
|
||||
path: str,
|
||||
value: Any,
|
||||
*,
|
||||
index: Optional[int] = None,
|
||||
only_config=undefined,
|
||||
force_default=undefined,
|
||||
force_default_if_same=undefined,
|
||||
|
|
@ -1204,14 +1267,21 @@ class TiramisuContextValue(TiramisuConfig, _TiramisuODGet):
|
|||
kwargs["force_default_if_same"] = force_default_if_same
|
||||
if force_dont_change_value is not undefined:
|
||||
kwargs["force_dont_change_value"] = force_dont_change_value
|
||||
option_bag = OptionBag(
|
||||
None,
|
||||
None,
|
||||
self._config_bag,
|
||||
path=path,
|
||||
)
|
||||
context = self._config_bag.context
|
||||
if isinstance(context, KernelGroupConfig):
|
||||
subconfig = Fake_SubConfig(self._config_bag,
|
||||
path,
|
||||
index,
|
||||
)
|
||||
else:
|
||||
subconfig = context.get_sub_config(
|
||||
self._config_bag,
|
||||
path,
|
||||
index,
|
||||
validate_properties=False,
|
||||
)
|
||||
return self._config_bag.context.set_value(
|
||||
option_bag,
|
||||
subconfig,
|
||||
value,
|
||||
**kwargs,
|
||||
)
|
||||
|
|
@ -1599,6 +1669,7 @@ class TiramisuContextOption(TiramisuConfig, _TiramisuOptionWalk):
|
|||
*,
|
||||
validate_properties: bool = True,
|
||||
uncalculated: bool = False,
|
||||
with_index: bool = True,
|
||||
):
|
||||
"""List options (by default list only option)"""
|
||||
root = self._config_bag.context.get_root(self._config_bag)
|
||||
|
|
@ -1606,6 +1677,7 @@ class TiramisuContextOption(TiramisuConfig, _TiramisuOptionWalk):
|
|||
root,
|
||||
validate_properties,
|
||||
uncalculated=uncalculated,
|
||||
with_index=with_index,
|
||||
)
|
||||
|
||||
def _load_dict(self, clearable="all", remotable="minimum"):
|
||||
|
|
@ -1912,7 +1984,7 @@ class Config(TiramisuAPI, TiramisuContextOption):
|
|||
return f"<Config path=None>"
|
||||
|
||||
|
||||
class MetaConfig(TiramisuAPI):
|
||||
class MetaConfig(TiramisuAPI, TiramisuContextOption):
|
||||
"""MetaConfig object that enables us to handle the sub configuration's options
|
||||
with common root optiondescription
|
||||
"""
|
||||
|
|
@ -1980,7 +2052,7 @@ class MixConfig(TiramisuAPI):
|
|||
display_name=display_name,
|
||||
)
|
||||
settings = config.get_settings()
|
||||
properties = settings.get_context_properties(config.properties_cache)
|
||||
properties = settings.get_context_properties()
|
||||
permissives = settings.get_context_permissives()
|
||||
config_bag = ConfigBag(
|
||||
config,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (C) 2012-2024 Team tiramisu (see AUTHORS for all contributors)
|
||||
# Copyright (C) 2012-2025 Team tiramisu (see AUTHORS for all contributors)
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Lesser General Public License as published by the
|
||||
|
|
@ -91,12 +91,12 @@ class CCache:
|
|||
if option.issubdyn():
|
||||
# it's an option in dynoptiondescription, remove cache for all generated option
|
||||
self.reset_cache_dyn_option(
|
||||
config_bag,
|
||||
subconfig,
|
||||
option,
|
||||
resetted_opts,
|
||||
)
|
||||
elif option.impl_is_dynoptiondescription():
|
||||
self._reset_cache_dyn_optiondescription(
|
||||
self.reset_cache_dyn_optiondescription(
|
||||
option,
|
||||
config_bag,
|
||||
resetted_opts,
|
||||
|
|
@ -120,13 +120,7 @@ class CCache:
|
|||
resetted_opts,
|
||||
)
|
||||
|
||||
def _reset_cache_dyn_optiondescription(
|
||||
self,
|
||||
option,
|
||||
config_bag,
|
||||
resetted_opts,
|
||||
):
|
||||
# reset cache for all chidren
|
||||
def get_dynamic_from_dyn_optiondescription(self, config_bag, option):
|
||||
path = option.impl_getpath()
|
||||
if "." in path:
|
||||
parent_path = path.rsplit(".", 1)[0]
|
||||
|
|
@ -139,9 +133,21 @@ class CCache:
|
|||
)
|
||||
else:
|
||||
parent_subconfig = self.get_root(config_bag)
|
||||
for subconfig in parent_subconfig.dyn_to_subconfig(
|
||||
return parent_subconfig.dyn_to_subconfig(
|
||||
option,
|
||||
False,
|
||||
)
|
||||
|
||||
def reset_cache_dyn_optiondescription(
|
||||
self,
|
||||
option,
|
||||
config_bag,
|
||||
resetted_opts,
|
||||
):
|
||||
# reset cache for all chidren
|
||||
for subconfig in self.get_dynamic_from_dyn_optiondescription(
|
||||
config_bag,
|
||||
option,
|
||||
):
|
||||
self.reset_one_option_cache(
|
||||
subconfig,
|
||||
|
|
@ -157,15 +163,20 @@ class CCache:
|
|||
resetted_opts,
|
||||
)
|
||||
|
||||
def reset_cache_dyn_option(
|
||||
self,
|
||||
config_bag,
|
||||
option,
|
||||
resetted_opts,
|
||||
):
|
||||
currents = [self.get_root(config_bag)]
|
||||
def get_dynamic_from_dyn_option(self, subconfig, option):
|
||||
config_bag = subconfig.config_bag
|
||||
sub_paths = option.impl_getpath()
|
||||
for sub_path in sub_paths.split("."):
|
||||
current_paths = subconfig.path.split('.')
|
||||
current_paths_max_index = len(current_paths) - 1
|
||||
current_subconfigs = []
|
||||
parent = subconfig
|
||||
while True:
|
||||
current_subconfigs.insert(0, parent)
|
||||
parent = parent.parent
|
||||
if parent.path is None:
|
||||
break
|
||||
currents = [self.get_root(config_bag)]
|
||||
for idx, sub_path in enumerate(sub_paths.split(".")):
|
||||
new_currents = []
|
||||
for current in currents:
|
||||
sub_option = current.option.get_child(
|
||||
|
|
@ -175,15 +186,17 @@ class CCache:
|
|||
allow_dynoption=True,
|
||||
)
|
||||
if sub_option.impl_is_dynoptiondescription():
|
||||
new_currents.extend(
|
||||
list(
|
||||
current.dyn_to_subconfig(
|
||||
sub_option,
|
||||
False,
|
||||
if idx <= current_paths_max_index and sub_option == current_subconfigs[idx].option:
|
||||
new_currents.append(current_subconfigs[idx])
|
||||
else:
|
||||
new_currents.extend(
|
||||
list(
|
||||
current.dyn_to_subconfig(
|
||||
sub_option,
|
||||
False,
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
else:
|
||||
new_currents.append(
|
||||
current.get_child(
|
||||
|
|
@ -194,7 +207,15 @@ class CCache:
|
|||
),
|
||||
)
|
||||
currents = new_currents
|
||||
for dyn_option_subconfig in currents:
|
||||
return currents
|
||||
|
||||
def reset_cache_dyn_option(
|
||||
self,
|
||||
subconfig,
|
||||
option,
|
||||
resetted_opts,
|
||||
):
|
||||
for dyn_option_subconfig in self.get_dynamic_from_dyn_option(subconfig, option):
|
||||
self.reset_one_option_cache(
|
||||
dyn_option_subconfig,
|
||||
resetted_opts,
|
||||
|
|
@ -348,8 +369,9 @@ class SubConfig:
|
|||
validate_properties,
|
||||
*,
|
||||
uncalculated: bool = False,
|
||||
with_index: bool = True,
|
||||
):
|
||||
if self.option.impl_is_leadership() and not uncalculated:
|
||||
if self.option.impl_is_leadership() and not uncalculated and with_index:
|
||||
yield from self.get_leadership_children(validate_properties)
|
||||
else:
|
||||
for child in self.option.get_children():
|
||||
|
|
@ -536,6 +558,19 @@ class SubConfig:
|
|||
return subconfigs
|
||||
return subconfigs[0]
|
||||
|
||||
def change_context(self, context) -> "SubConfig":
|
||||
config_bag = self.config_bag.copy()
|
||||
config_bag.context = context
|
||||
return SubConfig(self.option,
|
||||
self.index,
|
||||
self.path,
|
||||
config_bag,
|
||||
self.parent,
|
||||
self.identifiers,
|
||||
true_path=self.true_path,
|
||||
validate_properties=False,
|
||||
)
|
||||
|
||||
|
||||
class _Config(CCache):
|
||||
"""Sub configuration management entry.
|
||||
|
|
@ -816,6 +851,17 @@ class _Config(CCache):
|
|||
|
||||
# =============================================================================
|
||||
# Manage value
|
||||
def set_value(self,
|
||||
subconfig,
|
||||
value: Any,
|
||||
) -> Any:
|
||||
"""set value
|
||||
"""
|
||||
self.get_settings().validate_properties(subconfig)
|
||||
return self.get_values().set_value(subconfig,
|
||||
value
|
||||
)
|
||||
|
||||
def get_value(
|
||||
self,
|
||||
subconfig,
|
||||
|
|
@ -935,6 +981,8 @@ class _Config(CCache):
|
|||
def get_owner(
|
||||
self,
|
||||
subconfig: "SubConfig",
|
||||
*,
|
||||
validate_meta=True,
|
||||
):
|
||||
"""get owner"""
|
||||
subconfigs = self._get(
|
||||
|
|
@ -945,13 +993,14 @@ class _Config(CCache):
|
|||
for sc in subconfigs:
|
||||
owner = self.get_owner(
|
||||
sc,
|
||||
validate_meta=validate_meta,
|
||||
)
|
||||
if owner != owners.default:
|
||||
break
|
||||
else:
|
||||
owner = owners.default
|
||||
else:
|
||||
owner = self.get_values().getowner(subconfigs)
|
||||
owner = self.get_values().getowner(subconfigs, validate_meta=validate_meta)
|
||||
return owner
|
||||
|
||||
|
||||
|
|
@ -1232,6 +1281,8 @@ class KernelGroupConfig(_CommonConfig):
|
|||
# pylint: disable=super-init-not-called
|
||||
names = []
|
||||
for child in children:
|
||||
if not isinstance(child, (KernelConfig, KernelGroupConfig)):
|
||||
raise TypeError(_("child must be a Config, GroupConfig, MixConfig or MetaConfig"))
|
||||
name_ = child._impl_name
|
||||
names.append(name_)
|
||||
if len(names) != len(set(names)):
|
||||
|
|
@ -1259,61 +1310,58 @@ class KernelGroupConfig(_CommonConfig):
|
|||
|
||||
def reset_cache(
|
||||
self,
|
||||
option_bag,
|
||||
subconfig,
|
||||
resetted_opts=None,
|
||||
):
|
||||
if resetted_opts is None:
|
||||
resetted_opts = []
|
||||
if isinstance(self, KernelMixConfig):
|
||||
super().reset_cache(
|
||||
option_bag,
|
||||
subconfig,
|
||||
resetted_opts=copy(resetted_opts),
|
||||
)
|
||||
for child in self._impl_children:
|
||||
if option_bag is not None:
|
||||
coption_bag = option_bag.copy()
|
||||
cconfig_bag = coption_bag.config_bag.copy()
|
||||
cconfig_bag.context = child
|
||||
coption_bag.config_bag = cconfig_bag
|
||||
if subconfig is not None:
|
||||
parent_subconfig = subconfig.change_context(child)
|
||||
else:
|
||||
coption_bag = None
|
||||
parent_subconfig = None
|
||||
child.reset_cache(
|
||||
coption_bag,
|
||||
parent_subconfig,
|
||||
resetted_opts=copy(resetted_opts),
|
||||
)
|
||||
|
||||
def set_value(
|
||||
self,
|
||||
option_bag,
|
||||
subconfig,
|
||||
value,
|
||||
only_config=False,
|
||||
):
|
||||
"""Setattr not in current KernelGroupConfig, but in each children"""
|
||||
ret = []
|
||||
for child in self._impl_children:
|
||||
cconfig_bag = option_bag.config_bag.copy()
|
||||
cconfig_bag = subconfig.config_bag.copy()
|
||||
cconfig_bag.context = child
|
||||
if isinstance(child, KernelGroupConfig):
|
||||
ret.extend(
|
||||
child.set_value(
|
||||
option_bag,
|
||||
subconfig,
|
||||
value,
|
||||
only_config=only_config,
|
||||
)
|
||||
)
|
||||
else:
|
||||
settings = child.get_settings()
|
||||
properties = settings.get_context_properties(child.properties_cache)
|
||||
properties = settings.get_context_properties()
|
||||
permissives = settings.get_context_permissives()
|
||||
cconfig_bag.properties = properties
|
||||
cconfig_bag.permissives = permissives
|
||||
try:
|
||||
# GROUP
|
||||
coption_bag = child.get_sub_option_bag(
|
||||
coption_bag = child.get_sub_config(
|
||||
cconfig_bag,
|
||||
option_bag.path,
|
||||
option_bag.index,
|
||||
False,
|
||||
subconfig.path,
|
||||
subconfig.index,
|
||||
validate_properties=False,
|
||||
)
|
||||
child.set_value(
|
||||
coption_bag,
|
||||
|
|
@ -1323,7 +1371,7 @@ class KernelGroupConfig(_CommonConfig):
|
|||
# pylint: disable=protected-access
|
||||
ret.append(
|
||||
PropertiesOptionError(
|
||||
err._option_bag,
|
||||
err._subconfig,
|
||||
err.proptype,
|
||||
err._settings,
|
||||
err._opt_type,
|
||||
|
|
@ -1386,7 +1434,7 @@ class KernelGroupConfig(_CommonConfig):
|
|||
cconfig_bag.context = child
|
||||
if cconfig_bag.properties is None:
|
||||
settings = child.get_settings()
|
||||
properties = settings.get_context_properties(child.properties_cache)
|
||||
properties = settings.get_context_properties()
|
||||
permissives = settings.get_context_permissives()
|
||||
cconfig_bag.properties = properties
|
||||
cconfig_bag.permissives = permissives
|
||||
|
|
@ -1420,6 +1468,7 @@ class KernelGroupConfig(_CommonConfig):
|
|||
def reset(
|
||||
self,
|
||||
path: str,
|
||||
only_children: bool,
|
||||
config_bag: ConfigBag,
|
||||
) -> None:
|
||||
"""reset value for specified path"""
|
||||
|
|
@ -1428,19 +1477,19 @@ class KernelGroupConfig(_CommonConfig):
|
|||
cconfig_bag = config_bag.copy()
|
||||
cconfig_bag.context = child
|
||||
settings = child.get_settings()
|
||||
properties = settings.get_context_properties(child.properties_cache)
|
||||
properties = settings.get_context_properties()
|
||||
permissives = settings.get_context_permissives()
|
||||
cconfig_bag.properties = properties
|
||||
cconfig_bag.permissives = permissives
|
||||
cconfig_bag.remove_validation()
|
||||
# GROUP
|
||||
option_bag = child.get_sub_option_bag(
|
||||
subconfig = child.get_sub_config(
|
||||
cconfig_bag,
|
||||
path,
|
||||
None,
|
||||
False,
|
||||
)[-1]
|
||||
child.get_values().reset(option_bag)
|
||||
validate_properties=False,
|
||||
)
|
||||
child.get_values().reset(subconfig)
|
||||
|
||||
def getconfig(
|
||||
self,
|
||||
|
|
@ -1495,7 +1544,7 @@ class KernelMixConfig(KernelGroupConfig):
|
|||
|
||||
def set_value(
|
||||
self,
|
||||
option_bag,
|
||||
subconfig,
|
||||
value,
|
||||
only_config=False,
|
||||
force_default=False,
|
||||
|
|
@ -1526,10 +1575,10 @@ class KernelMixConfig(KernelGroupConfig):
|
|||
)
|
||||
)
|
||||
for child in self._impl_children:
|
||||
cconfig_bag = option_bag.config_bag.copy()
|
||||
cconfig_bag = subconfig.config_bag.copy()
|
||||
cconfig_bag.context = child
|
||||
settings = child.get_settings()
|
||||
properties = settings.get_context_properties(child.properties_cache)
|
||||
properties = settings.get_context_properties()
|
||||
cconfig_bag.properties = properties
|
||||
cconfig_bag.permissives = settings.get_context_permissives()
|
||||
try:
|
||||
|
|
@ -1541,14 +1590,14 @@ class KernelMixConfig(KernelGroupConfig):
|
|||
not force_default and not force_default_if_same
|
||||
)
|
||||
# MIX
|
||||
moption_bag = obj.get_sub_option_bag(
|
||||
moption_bag = obj.get_sub_config(
|
||||
cconfig_bag,
|
||||
option_bag.path,
|
||||
option_bag.index,
|
||||
validate_properties,
|
||||
)[-1]
|
||||
subconfig.path,
|
||||
subconfig.index,
|
||||
validate_properties=validate_properties,
|
||||
)
|
||||
if force_default_if_same:
|
||||
if not child.get_values().hasvalue(option_bag.path):
|
||||
if not child.get_values().hasvalue(subconfig.path, index=subconfig.index):
|
||||
child_value = undefined
|
||||
else:
|
||||
child_value = child.get_value(moption_bag)
|
||||
|
|
@ -1568,7 +1617,7 @@ class KernelMixConfig(KernelGroupConfig):
|
|||
# pylint: disable=protected-access
|
||||
ret.append(
|
||||
PropertiesOptionError(
|
||||
err._option_bag,
|
||||
err._subconfig,
|
||||
err.proptype,
|
||||
err._settings,
|
||||
err._opt_type,
|
||||
|
|
@ -1581,12 +1630,12 @@ class KernelMixConfig(KernelGroupConfig):
|
|||
|
||||
try:
|
||||
# MIX
|
||||
moption_bag = self.get_sub_option_bag(
|
||||
option_bag.config_bag,
|
||||
option_bag.path,
|
||||
option_bag.index,
|
||||
not only_config,
|
||||
)[-1]
|
||||
moption_bag = self.get_sub_config(
|
||||
subconfig.config_bag,
|
||||
subconfig.path,
|
||||
subconfig.index,
|
||||
validate_properties=not only_config,
|
||||
)
|
||||
if only_config:
|
||||
ret = super().set_value(
|
||||
moption_bag,
|
||||
|
|
@ -1615,37 +1664,37 @@ class KernelMixConfig(KernelGroupConfig):
|
|||
rconfig_bag.remove_validation()
|
||||
if self.impl_type == "meta":
|
||||
# MIX
|
||||
option_bag = self.get_sub_option_bag(
|
||||
subconfig = self.get_sub_config(
|
||||
config_bag,
|
||||
path,
|
||||
None,
|
||||
True,
|
||||
)[-1]
|
||||
validate_properties=True,
|
||||
)
|
||||
elif not only_children:
|
||||
try:
|
||||
# MIX
|
||||
option_bag = self.get_sub_option_bag(
|
||||
subconfig = self.get_sub_config(
|
||||
rconfig_bag,
|
||||
path,
|
||||
None,
|
||||
True,
|
||||
)[-1]
|
||||
validate_properties=True,
|
||||
)
|
||||
except AttributeError:
|
||||
only_children = True
|
||||
for child in self._impl_children:
|
||||
rconfig_bag.context = child
|
||||
try:
|
||||
if self.impl_type == "meta":
|
||||
moption_bag = option_bag
|
||||
moption_bag = subconfig
|
||||
moption_bag.config_bag = rconfig_bag
|
||||
else:
|
||||
# MIX
|
||||
moption_bag = child.get_sub_option_bag(
|
||||
moption_bag = child.get_sub_config(
|
||||
rconfig_bag,
|
||||
path,
|
||||
None,
|
||||
True,
|
||||
)[-1]
|
||||
validate_properties=True,
|
||||
)
|
||||
child.get_values().reset(moption_bag)
|
||||
except AttributeError:
|
||||
pass
|
||||
|
|
@ -1656,8 +1705,8 @@ class KernelMixConfig(KernelGroupConfig):
|
|||
rconfig_bag,
|
||||
)
|
||||
if not only_children:
|
||||
option_bag.config_bag = config_bag
|
||||
self.get_values().reset(option_bag)
|
||||
subconfig.config_bag = config_bag
|
||||
self.get_values().reset(subconfig)
|
||||
|
||||
def new_config(
|
||||
self,
|
||||
|
|
|
|||
|
|
@ -249,19 +249,19 @@ class LeadershipError(Exception):
|
|||
option = subconfig.option
|
||||
self.display_name = option.impl_get_display_name(subconfig, with_quote=True)
|
||||
self.code = code
|
||||
if prop:
|
||||
if prop is not None:
|
||||
self.prop = prop
|
||||
if index:
|
||||
if index is not None:
|
||||
self.index = index
|
||||
if length:
|
||||
if length is not None:
|
||||
self.length = length
|
||||
if callback:
|
||||
if callback is not None:
|
||||
self.callback = callback
|
||||
if args:
|
||||
if args is not None:
|
||||
self.args = args
|
||||
if kwargs:
|
||||
if kwargs is not None:
|
||||
self.kwargs = kwargs
|
||||
if ret:
|
||||
if ret is not None:
|
||||
self.ret = ret
|
||||
|
||||
def __str__(self):
|
||||
|
|
@ -310,6 +310,8 @@ class _CommonError:
|
|||
self.display_type = display_type
|
||||
self.opt = weakref.ref(opt)
|
||||
self.name = opt.impl_get_display_name(subconfig, with_quote=True)
|
||||
if subconfig:
|
||||
self.path = subconfig.path
|
||||
self.err_msg = err_msg
|
||||
self.index = index
|
||||
super().__init__(self.err_msg)
|
||||
|
|
@ -394,6 +396,12 @@ class CancelParam(Exception):
|
|||
return False
|
||||
|
||||
|
||||
class ValueErrorIndexes(ValueError):
|
||||
def __init__(self, msg, indexes):
|
||||
super().__init__(msg)
|
||||
self.indexes = indexes
|
||||
|
||||
|
||||
class Errors:
|
||||
@staticmethod
|
||||
def raise_carry_out_calculation_error(
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -145,7 +145,7 @@ class DynOptionDescription(OptionDescription):
|
|||
)
|
||||
else:
|
||||
values_.append(val)
|
||||
if __debug__ and len(values_) > len(set(values_)):
|
||||
if __debug__ and "demoting_error_warning" not in subconfig.config_bag.properties and len(values_) > len(set(values_)):
|
||||
raise ValueError(
|
||||
_(
|
||||
'DynOptionDescription "{0}" identifiers return a list with same values "{1}"'
|
||||
|
|
|
|||
|
|
@ -281,17 +281,14 @@ class Option(BaseOption):
|
|||
force_index = None
|
||||
is_warnings_only = getattr(self, "_warnings_only", False)
|
||||
|
||||
def _is_not_unique(value):
|
||||
# if set(value) has not same length than value
|
||||
def _is_not_unique(current_value, values):
|
||||
if current_value is None:
|
||||
return
|
||||
if not subconfig or not check_error or "unique" not in subconfig.properties:
|
||||
return
|
||||
lvalue = [val for val in value if val is not None]
|
||||
if len(set(lvalue)) == len(lvalue):
|
||||
return
|
||||
for idx, val in enumerate(value):
|
||||
if val not in value[idx + 1 :]:
|
||||
continue
|
||||
raise ValueError(_('the value "{}" is not unique' "").format(val))
|
||||
indexes = [index for index, value in enumerate(values) if value == current_value]
|
||||
if len(indexes) > 1:
|
||||
raise ValueError(_('the value "{}" is not unique' "").format(current_value))
|
||||
|
||||
def calculation_validator(
|
||||
val,
|
||||
|
|
@ -394,80 +391,100 @@ class Option(BaseOption):
|
|||
_index,
|
||||
)
|
||||
|
||||
val = value
|
||||
err_index = force_index
|
||||
try:
|
||||
if not self.impl_is_multi():
|
||||
ret = True
|
||||
if not self.impl_is_multi():
|
||||
try:
|
||||
do_validation(
|
||||
val,
|
||||
value,
|
||||
None,
|
||||
)
|
||||
elif force_index is not None:
|
||||
if self.impl_is_submulti():
|
||||
if not isinstance(value, list):
|
||||
raise ValueError(_("which must be a list"))
|
||||
for val in value:
|
||||
except ValueError as err:
|
||||
self.validate_parse_error(value, err_index, err, subconfig)
|
||||
ret = False
|
||||
elif force_index is not None:
|
||||
if self.impl_is_submulti():
|
||||
if not isinstance(value, list):
|
||||
raise ValueError(_("which must be a list"))
|
||||
for val in value:
|
||||
try:
|
||||
do_validation(
|
||||
val,
|
||||
force_index,
|
||||
)
|
||||
_is_not_unique(value)
|
||||
else:
|
||||
_is_not_unique(val, value)
|
||||
except ValueError as err:
|
||||
self.validate_parse_error(val, err_index, err, subconfig)
|
||||
ret = False
|
||||
else:
|
||||
try:
|
||||
do_validation(
|
||||
val,
|
||||
value,
|
||||
force_index,
|
||||
)
|
||||
elif isinstance(value, Calculation) and not subconfig:
|
||||
pass
|
||||
elif self.impl_is_submulti():
|
||||
for err_index, lval in enumerate(value):
|
||||
if isinstance(lval, Calculation):
|
||||
continue
|
||||
if not isinstance(lval, list):
|
||||
raise ValueError(
|
||||
_('which "{}" must be a list of list' "").format(lval)
|
||||
)
|
||||
for val in lval:
|
||||
except ValueError as err:
|
||||
self.validate_parse_error(value, err_index, err, subconfig)
|
||||
ret = False
|
||||
elif isinstance(value, Calculation) and not subconfig:
|
||||
pass
|
||||
elif self.impl_is_submulti():
|
||||
for err_index, lval in enumerate(value):
|
||||
if isinstance(lval, Calculation):
|
||||
continue
|
||||
if not isinstance(lval, list):
|
||||
raise ValueError(
|
||||
_('which "{}" must be a list of list' "").format(lval)
|
||||
)
|
||||
for val in lval:
|
||||
try:
|
||||
do_validation(val, err_index)
|
||||
_is_not_unique(lval)
|
||||
elif not isinstance(value, list):
|
||||
raise ValueError(_("which must be a list"))
|
||||
else:
|
||||
# FIXME suboptimal, not several time for whole=True!
|
||||
for err_index, val in enumerate(value):
|
||||
_is_not_unique(val, lval)
|
||||
except ValueError as err:
|
||||
self.validate_parse_error(val, err_index, err, subconfig)
|
||||
ret = False
|
||||
elif not isinstance(value, list):
|
||||
raise ValueError(_("which must be a list"))
|
||||
else:
|
||||
# FIXME suboptimal, not several time for whole=True!
|
||||
for err_index, val in enumerate(value):
|
||||
try:
|
||||
do_validation(
|
||||
val,
|
||||
err_index,
|
||||
)
|
||||
_is_not_unique(value)
|
||||
except ValueError as err:
|
||||
if (
|
||||
not subconfig
|
||||
or "demoting_error_warning" not in subconfig.config_bag.properties
|
||||
):
|
||||
raise ValueOptionError(
|
||||
subconfig=subconfig,
|
||||
val=val,
|
||||
display_type=_(self.get_type()),
|
||||
opt=self,
|
||||
err_msg=str(err),
|
||||
index=err_index,
|
||||
) from err
|
||||
warnings.warn_explicit(
|
||||
ValueErrorWarning(
|
||||
subconfig=subconfig,
|
||||
val=val,
|
||||
display_type=_(self.get_type()),
|
||||
opt=self,
|
||||
err_msg=str(err),
|
||||
index=err_index,
|
||||
),
|
||||
ValueErrorWarning,
|
||||
self.__class__.__name__,
|
||||
0,
|
||||
)
|
||||
return False
|
||||
return True
|
||||
_is_not_unique(val, value)
|
||||
except ValueError as err:
|
||||
self.validate_parse_error(val, err_index, err, subconfig)
|
||||
ret = False
|
||||
# return False
|
||||
return ret
|
||||
|
||||
def validate_parse_error(self, val, index, err, subconfig):
|
||||
if (
|
||||
not subconfig
|
||||
or "demoting_error_warning" not in subconfig.config_bag.properties
|
||||
):
|
||||
raise ValueOptionError(
|
||||
subconfig=subconfig,
|
||||
val=val,
|
||||
display_type=_(self.get_type()),
|
||||
opt=self,
|
||||
err_msg=str(err),
|
||||
index=index,
|
||||
) from err
|
||||
warnings.warn_explicit(
|
||||
ValueErrorWarning(
|
||||
subconfig=subconfig,
|
||||
val=val,
|
||||
display_type=_(self.get_type()),
|
||||
opt=self,
|
||||
err_msg=str(err),
|
||||
index=index,
|
||||
),
|
||||
ValueErrorWarning,
|
||||
self.__class__.__name__,
|
||||
0,
|
||||
)
|
||||
|
||||
def validate_with_option(
|
||||
self,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"sets the options of the configuration objects Config object itself"
|
||||
# Copyright (C) 2012-2024 Team tiramisu (see AUTHORS for all contributors)
|
||||
# Copyright (C) 2012-2025 Team tiramisu (see AUTHORS for all contributors)
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Lesser General Public License as published by the
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"takes care of the option's values and multi values"
|
||||
# Copyright (C) 2013-2024 Team tiramisu (see AUTHORS for all contributors)
|
||||
# Copyright (C) 2013-2025 Team tiramisu (see AUTHORS for all contributors)
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Lesser General Public License as published by the
|
||||
|
|
@ -189,10 +189,9 @@ class Values:
|
|||
if subconfig.config_bag.context.impl_type == "config":
|
||||
return True
|
||||
# it's a not a config, force to metaconfig only in *explicitly* set
|
||||
return "force_metaconfig_on_freeze" in settings.get_stored_properties(
|
||||
return "force_metaconfig_on_freeze" in settings.get_personalize_properties(
|
||||
subconfig.path,
|
||||
subconfig.index,
|
||||
frozenset(),
|
||||
)
|
||||
return False
|
||||
|
||||
|
|
@ -434,36 +433,28 @@ class Values:
|
|||
If not found, return None
|
||||
For follower option, return the Config where leader is modified
|
||||
"""
|
||||
|
||||
def build_option_bag(subconfig, parent):
|
||||
doption_bag = subconfig.copy()
|
||||
config_bag = subconfig.config_bag.copy()
|
||||
config_bag.context = parent
|
||||
config_bag.unrestraint()
|
||||
doption_bag.config_bag = config_bag
|
||||
return doption_bag
|
||||
|
||||
for parent in subconfig.config_bag.context.get_parents():
|
||||
doption_bag = build_option_bag(subconfig, parent)
|
||||
parent_subconfig = subconfig.change_context(parent)
|
||||
parent_subconfig.config_bag.unrestraint()
|
||||
parent_subconfig.properties = subconfig.properties
|
||||
if "force_metaconfig_on_freeze" in subconfig.properties:
|
||||
# remove force_metaconfig_on_freeze only if option in metaconfig
|
||||
# hasn't force_metaconfig_on_freeze properties
|
||||
ori_properties = doption_bag.properties
|
||||
settings = doption_bag.config_bag.context.get_settings()
|
||||
doption_bag.properties = settings.getproperties(doption_bag)
|
||||
if not self.check_force_to_metaconfig(doption_bag):
|
||||
doption_bag.properties = ori_properties - {
|
||||
ori_properties = parent_subconfig.properties
|
||||
settings = parent_subconfig.config_bag.context.get_settings()
|
||||
parent_subconfig.properties = settings.getproperties(parent_subconfig)
|
||||
if not self.check_force_to_metaconfig(parent_subconfig):
|
||||
parent_subconfig.properties = ori_properties - {
|
||||
"force_metaconfig_on_freeze"
|
||||
}
|
||||
else:
|
||||
doption_bag.properties = ori_properties
|
||||
parent_subconfig.properties = ori_properties
|
||||
parent_owner = parent.get_values().getowner(
|
||||
doption_bag,
|
||||
parent,
|
||||
parent_subconfig,
|
||||
only_default=True,
|
||||
)
|
||||
if parent_owner != owners.default:
|
||||
return doption_bag
|
||||
return parent_subconfig
|
||||
|
||||
return None
|
||||
|
||||
|
|
@ -517,9 +508,6 @@ class Values:
|
|||
was present
|
||||
:returns: a `setting.owners.Owner` object
|
||||
"""
|
||||
# context = subconfig.config_bag.context
|
||||
# settings = context.get_settings()
|
||||
# settings.validate_properties(subconfig)
|
||||
if (
|
||||
"frozen" in subconfig.properties
|
||||
and "force_default_on_freeze" in subconfig.properties
|
||||
|
|
@ -548,11 +536,10 @@ class Values:
|
|||
values = msubconfig.config_bag.context.get_values()
|
||||
owner = values.getowner(
|
||||
msubconfig,
|
||||
parent,
|
||||
only_default=only_default,
|
||||
)
|
||||
elif "force_metaconfig_on_freeze" in subconfig.properties:
|
||||
return owners.default
|
||||
owner = owners.default
|
||||
return owner
|
||||
|
||||
def set_owner(
|
||||
|
|
@ -749,8 +736,8 @@ class Values:
|
|||
if index >= length:
|
||||
raise IndexError(
|
||||
_(
|
||||
"index {index} is greater than the length {length} "
|
||||
"for option {subconfig.option.impl_get_display_name(with_quote=True)}"
|
||||
f"index {index} is greater than the length {length} "
|
||||
f"for option {subconfig.option.impl_get_display_name(subconfig, with_quote=True)}"
|
||||
)
|
||||
)
|
||||
current_value.pop(index)
|
||||
|
|
|
|||
Loading…
Reference in a new issue