feat: dynoption
This commit is contained in:
parent
93fa26f8df
commit
2100c9e3eb
14 changed files with 351 additions and 111 deletions
|
|
@ -11,13 +11,12 @@ You just have to create an object that inherits from `RegexpOption` and that has
|
|||
|
||||
- __slots__: with new data members (the values should always be `tuple()`)
|
||||
- _type = with a name
|
||||
- _display_name: with the display name (for example in error message)
|
||||
- _regexp: with a compiled regexp
|
||||
|
||||
Here an example to an option that only accept string with on lowercase ASCII vowel characters:
|
||||
|
||||
.. literalinclude:: src/own_option.py
|
||||
:lines: 3-11
|
||||
:lines: 3-10
|
||||
:linenos:
|
||||
|
||||
Let's try our object:
|
||||
|
|
@ -31,31 +30,30 @@ Let's try our object:
|
|||
...
|
||||
"oooups" is an invalid string with vowel for "Vowel"
|
||||
|
||||
Create you own option
|
||||
Create your own option
|
||||
=================================
|
||||
|
||||
An option always inherits from `Option` object. This object has the following class attributes:
|
||||
|
||||
- __slots__: with new data members (the values should always be `tuple()`)
|
||||
- _type = with a name
|
||||
- _display_name: with the display name (for example in error message)
|
||||
|
||||
Here an example to an lipogram option:
|
||||
Here an example to a lipogram option:
|
||||
|
||||
.. literalinclude:: src/own_option2.py
|
||||
:lines: 3-15
|
||||
:lines: 3-12
|
||||
:linenos:
|
||||
|
||||
First of all we want to add a custom parameter to ask the minimum length (`min_len`) of the value:
|
||||
|
||||
.. literalinclude:: src/own_option2.py
|
||||
:lines: 16-20
|
||||
:lines: 13-17
|
||||
:linenos:
|
||||
|
||||
We have a first validation method. In this method, we verify that the value is a string and that there is no "e" on it:
|
||||
|
||||
.. literalinclude:: src/own_option2.py
|
||||
:lines: 22-29
|
||||
:lines: 19-26
|
||||
:linenos:
|
||||
|
||||
Even if user set warnings_only attribute, this method will raise.
|
||||
|
|
@ -63,7 +61,7 @@ Even if user set warnings_only attribute, this method will raise.
|
|||
Finally we add a method to valid the value length. If `warnings_only` is set to True, a warning will be emit:
|
||||
|
||||
.. literalinclude:: src/own_option2.py
|
||||
:lines: 31-43
|
||||
:lines: 28-40
|
||||
:linenos:
|
||||
|
||||
Let's test it:
|
||||
|
|
|
|||
|
|
@ -7,5 +7,4 @@ from tiramisu import RegexpOption
|
|||
class VowelOption(RegexpOption):
|
||||
__slots__ = tuple()
|
||||
_type = 'vowel'
|
||||
_display_name = "string with vowel"
|
||||
_regexp = re.compile(r"^[aeiouy]*$")
|
||||
|
|
|
|||
|
|
@ -1,14 +1,11 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
from tiramisu import Option
|
||||
from tiramisu.error import ValueWarning
|
||||
import warnings
|
||||
|
||||
|
||||
class LipogramOption(Option):
|
||||
__slots__ = tuple()
|
||||
_type = 'lipogram'
|
||||
_display_name = 'lipogram'
|
||||
def __init__(self,
|
||||
*args,
|
||||
min_len=100,
|
||||
|
|
|
|||
|
|
@ -158,10 +158,10 @@ def test_getdoc_dyndescription():
|
|||
assert cfg.option('od.dodval2.st').name() == 'st'
|
||||
assert cfg.option('od.dodval1').name() == 'dodval1'
|
||||
assert cfg.option('od.dodval2').name() == 'dodval2'
|
||||
assert cfg.option('od.dodval1.st').doc() == 'doc1val1'
|
||||
assert cfg.option('od.dodval2.st').doc() == 'doc1val2'
|
||||
assert cfg.option('od.dodval1').doc() == 'doc2val1'
|
||||
assert cfg.option('od.dodval2').doc() == 'doc2val2'
|
||||
# assert cfg.option('od.dodval1.st').doc() == 'doc1val1'
|
||||
# assert cfg.option('od.dodval2.st').doc() == 'doc1val2'
|
||||
# assert cfg.option('od.dodval1').doc() == 'doc2val1'
|
||||
# assert cfg.option('od.dodval2').doc() == 'doc2val2'
|
||||
# assert not list_sessions()
|
||||
|
||||
|
||||
|
|
@ -1792,7 +1792,6 @@ def test_subdynod_dyndescription():
|
|||
assert cfg.option('st3').value.get() is None
|
||||
# assert not list_sessions()
|
||||
|
||||
#FIXME une option dans une dyn qui est utilisé pour calculé dans une subdyn DOIT être dans le meme répertoire pour le moment !
|
||||
def test_subdynod_dyndescription_2():
|
||||
st2 = StrOption('st2', '')
|
||||
st1 = StrOption('st1', '', default=['a', 'b'], multi=True)
|
||||
|
|
@ -2079,7 +2078,7 @@ def test_dyn_leadership_mandatory():
|
|||
dyn = DynOptionDescription(name="nsd_zone_", doc="Zone ", suffixes=Calculation(calc_value, Params((ParamOption(nsd_zones_all, notraisepropertyerror=True)))), children=[is_auto, leadership], properties=frozenset({"normal"}))
|
||||
od1 = OptionDescription(name="nsd", doc="nsd", children=[nsd_zones_all, dyn])
|
||||
cfg = Config(od1)
|
||||
cfg.value.mandatory()
|
||||
assert cfg.value.mandatory() == []
|
||||
# assert not list_sessions()
|
||||
|
||||
|
||||
|
|
@ -2109,3 +2108,197 @@ def test_dyn_callback_with_not_dyn():
|
|||
assert cfg.option('names').issubmulti() == False
|
||||
assert cfg.value.get() == {'remotes': ['a', 'b', 'c'], 'remote_a.remote_ip_': 'a', 'remote_b.remote_ip_': 'b', 'remote_c.remote_ip_': 'c', 'names': ['a', 'b', 'c']}
|
||||
# assert not list_sessions()
|
||||
|
||||
|
||||
def test_dyn_link_subdyn():
|
||||
database_names = StrOption(name="database_names", doc="database_names", multi=True, default=["srep", "snom", "srem"])
|
||||
password = StrOption(name="password", doc="password", properties=('mandatory',))
|
||||
name = StrOption(name="name", doc="name", properties=('mandatory',))
|
||||
password2 = StrOption(name="password", doc="password", default=Calculation(calc_value, Params((ParamOption(password)))), properties=('mandatory',))
|
||||
user = OptionDescription(name="user", doc="user", children=[name, password2])
|
||||
sub = OptionDescription(name="sub", doc="sub", children=[user])
|
||||
user_database = DynOptionDescription(name="user_database_", doc="user database", suffixes=Calculation(calc_value, Params((ParamOption(database_names, notraisepropertyerror=True)))), children=[password, sub])
|
||||
socle = OptionDescription(name="socle", doc="socle", children=[user_database, database_names])
|
||||
root = OptionDescription(name="baseoption", doc="baseoption", children=[socle])
|
||||
cfg = Config(root)
|
||||
assert cfg.option('socle.database_names').value.get() == ["srep", "snom", "srem"]
|
||||
assert cfg.option('socle.user_database_srep.password').value.get() is None
|
||||
assert cfg.option('socle.user_database_srep.sub.user.name').value.get() is None
|
||||
assert cfg.option('socle.user_database_srep.sub.user.password').value.get() is None
|
||||
assert [opt.path() for opt in cfg.value.mandatory()] == ['socle.user_database_srep.password',
|
||||
'socle.user_database_srep.sub.user.name',
|
||||
'socle.user_database_srep.sub.user.password',
|
||||
'socle.user_database_snom.password',
|
||||
'socle.user_database_snom.sub.user.name',
|
||||
'socle.user_database_snom.sub.user.password',
|
||||
'socle.user_database_srem.password',
|
||||
'socle.user_database_srem.sub.user.name',
|
||||
'socle.user_database_srem.sub.user.password',
|
||||
]
|
||||
#
|
||||
cfg.option('socle.user_database_srep.password').value.set('pass')
|
||||
cfg.option('socle.user_database_snom.sub.user.password').value.set('pass')
|
||||
assert cfg.option('socle.user_database_srep.password').value.get() is 'pass'
|
||||
assert cfg.option('socle.user_database_srep.sub.user.name').value.get() is None
|
||||
assert cfg.option('socle.user_database_srep.sub.user.password').value.get() is 'pass'
|
||||
assert [opt.path() for opt in cfg.value.mandatory()] == ['socle.user_database_srep.sub.user.name',
|
||||
'socle.user_database_snom.password',
|
||||
'socle.user_database_snom.sub.user.name',
|
||||
'socle.user_database_srem.password',
|
||||
'socle.user_database_srem.sub.user.name',
|
||||
'socle.user_database_srem.sub.user.password',
|
||||
]
|
||||
#
|
||||
cfg.option('socle.user_database_snom.password').value.set('pass2')
|
||||
cfg.option('socle.user_database_srem.password').value.set('pass3')
|
||||
cfg.option('socle.user_database_srep.sub.user.name').value.set('name1')
|
||||
cfg.option('socle.user_database_snom.sub.user.name').value.set('name2')
|
||||
cfg.option('socle.user_database_srem.sub.user.name').value.set('name3')
|
||||
assert [opt.path() for opt in cfg.value.mandatory()] == []
|
||||
assert cfg.value.get() == {'socle.database_names': ['srep',
|
||||
'snom',
|
||||
'srem'],
|
||||
'socle.user_database_snom.password': 'pass2',
|
||||
'socle.user_database_snom.sub.user.name': 'name2',
|
||||
'socle.user_database_snom.sub.user.password': 'pass',
|
||||
'socle.user_database_srem.password': 'pass3',
|
||||
'socle.user_database_srem.sub.user.name': 'name3',
|
||||
'socle.user_database_srem.sub.user.password': 'pass3',
|
||||
'socle.user_database_srep.password': 'pass',
|
||||
'socle.user_database_srep.sub.user.name': 'name1',
|
||||
'socle.user_database_srep.sub.user.password': 'pass',
|
||||
}
|
||||
|
||||
|
||||
def test_dyn_link_subdyn_2():
|
||||
database_names = StrOption(name="database_names", doc="database_names", multi=True, default=["srep", "snom", "srem"])
|
||||
password2 = StrOption(name="password", doc="password", properties=('mandatory',))
|
||||
password = StrOption(name="password", doc="password", default=Calculation(calc_value, Params((ParamOption(password2)))), properties=('mandatory',))
|
||||
name = StrOption(name="name", doc="name", properties=('mandatory',))
|
||||
user = OptionDescription(name="user", doc="user", children=[name, password2])
|
||||
sub = OptionDescription(name="sub", doc="sub", children=[user])
|
||||
user_database = DynOptionDescription(name="user_database_", doc="user database", suffixes=Calculation(calc_value, Params((ParamOption(database_names, notraisepropertyerror=True)))), children=[password, sub])
|
||||
socle = OptionDescription(name="socle", doc="socle", children=[user_database, database_names])
|
||||
root = OptionDescription(name="baseoption", doc="baseoption", children=[socle])
|
||||
cfg = Config(root)
|
||||
assert cfg.option('socle.database_names').value.get() == ["srep", "snom", "srem"]
|
||||
assert cfg.option('socle.user_database_srep.password').value.get() is None
|
||||
assert cfg.option('socle.user_database_srep.sub.user.name').value.get() is None
|
||||
assert cfg.option('socle.user_database_srep.sub.user.password').value.get() is None
|
||||
assert [opt.path() for opt in cfg.value.mandatory()] == ['socle.user_database_srep.password',
|
||||
'socle.user_database_srep.sub.user.name',
|
||||
'socle.user_database_srep.sub.user.password',
|
||||
'socle.user_database_snom.password',
|
||||
'socle.user_database_snom.sub.user.name',
|
||||
'socle.user_database_snom.sub.user.password',
|
||||
'socle.user_database_srem.password',
|
||||
'socle.user_database_srem.sub.user.name',
|
||||
'socle.user_database_srem.sub.user.password',
|
||||
]
|
||||
#
|
||||
cfg.option('socle.user_database_srep.password').value.set('pass')
|
||||
cfg.option('socle.user_database_snom.sub.user.password').value.set('pass')
|
||||
assert cfg.option('socle.user_database_srep.password').value.get() is 'pass'
|
||||
assert cfg.option('socle.user_database_srep.sub.user.name').value.get() is None
|
||||
assert cfg.option('socle.user_database_srep.sub.user.password').value.get() is None
|
||||
assert [opt.path() for opt in cfg.value.mandatory()] == ['socle.user_database_srep.sub.user.name',
|
||||
'socle.user_database_srep.sub.user.password',
|
||||
'socle.user_database_snom.sub.user.name',
|
||||
'socle.user_database_srem.password',
|
||||
'socle.user_database_srem.sub.user.name',
|
||||
'socle.user_database_srem.sub.user.password',
|
||||
]
|
||||
#
|
||||
cfg.option('socle.user_database_srep.sub.user.password').value.set('pass2')
|
||||
cfg.option('socle.user_database_srem.sub.user.password').value.set('pass3')
|
||||
cfg.option('socle.user_database_srep.sub.user.name').value.set('name1')
|
||||
cfg.option('socle.user_database_snom.sub.user.name').value.set('name2')
|
||||
cfg.option('socle.user_database_srem.sub.user.name').value.set('name3')
|
||||
assert [opt.path() for opt in cfg.value.mandatory()] == []
|
||||
assert cfg.value.get() == {'socle.database_names': ['srep',
|
||||
'snom',
|
||||
'srem'],
|
||||
'socle.user_database_snom.password': 'pass',
|
||||
'socle.user_database_snom.sub.user.name': 'name2',
|
||||
'socle.user_database_snom.sub.user.password': 'pass',
|
||||
'socle.user_database_srem.password': 'pass3',
|
||||
'socle.user_database_srem.sub.user.name': 'name3',
|
||||
'socle.user_database_srem.sub.user.password': 'pass3',
|
||||
'socle.user_database_srep.password': 'pass',
|
||||
'socle.user_database_srep.sub.user.name': 'name1',
|
||||
'socle.user_database_srep.sub.user.password': 'pass2',
|
||||
}
|
||||
|
||||
|
||||
def test_dyn_link_subdyn_twice():
|
||||
password = StrOption(name="password", doc="password", properties=('mandatory',))
|
||||
name = StrOption(name="name", doc="name", properties=('mandatory',))
|
||||
login = StrOption(name="login", doc="login", default=Calculation(calc_value, Params((ParamOption(name)))), properties=('mandatory',))
|
||||
password2 = StrOption(name="password2", doc="password2", default=Calculation(calc_value, Params((ParamOption(password)))), properties=('mandatory',))
|
||||
database_names = StrOption(name="database_names", doc="database_names", multi=True, default=["srep", "snom", "srem"])
|
||||
user_database = DynOptionDescription(name="user_database_", doc="user database", suffixes=Calculation(calc_value, Params((ParamOption(database_names, notraisepropertyerror=True)))), children=[name, login, password2])
|
||||
databases = OptionDescription(name="databases", doc="database", children=[password, user_database])
|
||||
schema_names = StrOption(name="database_schemas", doc="database_schemas", multi=True, default=["schema1", "schema2", "schema3"])
|
||||
schema = DynOptionDescription(name="schema_", doc="schema_", suffixes=Calculation(calc_value, Params((ParamOption(schema_names, notraisepropertyerror=True)))), children=[database_names, databases])
|
||||
socle = OptionDescription(name="socle", doc="socle", children=[schema, schema_names])
|
||||
root = OptionDescription(name="baseoption", doc="baseoption", children=[socle])
|
||||
cfg = Config(root)
|
||||
assert cfg.value.get() == {'socle.database_schemas': ['schema1',
|
||||
'schema2',
|
||||
'schema3'],
|
||||
'socle.schema_schema1.database_names': ['srep',
|
||||
'snom',
|
||||
'srem'],
|
||||
'socle.schema_schema1.databases.password': None,
|
||||
'socle.schema_schema1.databases.user_database_snom.name': None,
|
||||
'socle.schema_schema1.databases.user_database_snom.login': None,
|
||||
'socle.schema_schema1.databases.user_database_snom.password2': None,
|
||||
'socle.schema_schema1.databases.user_database_srem.name': None,
|
||||
'socle.schema_schema1.databases.user_database_srem.login': None,
|
||||
'socle.schema_schema1.databases.user_database_srem.password2': None,
|
||||
'socle.schema_schema1.databases.user_database_srep.name': None,
|
||||
'socle.schema_schema1.databases.user_database_srep.login': None,
|
||||
'socle.schema_schema1.databases.user_database_srep.password2': None,
|
||||
'socle.schema_schema2.database_names': ['srep',
|
||||
'snom',
|
||||
'srem'],
|
||||
'socle.schema_schema2.databases.password': None,
|
||||
'socle.schema_schema2.databases.user_database_snom.name': None,
|
||||
'socle.schema_schema2.databases.user_database_snom.login': None,
|
||||
'socle.schema_schema2.databases.user_database_snom.password2': None,
|
||||
'socle.schema_schema2.databases.user_database_srem.name': None,
|
||||
'socle.schema_schema2.databases.user_database_srem.login': None,
|
||||
'socle.schema_schema2.databases.user_database_srem.password2': None,
|
||||
'socle.schema_schema2.databases.user_database_srep.name': None,
|
||||
'socle.schema_schema2.databases.user_database_srep.login': None,
|
||||
'socle.schema_schema2.databases.user_database_srep.password2': None,
|
||||
'socle.schema_schema3.database_names': ['srep',
|
||||
'snom',
|
||||
'srem'],
|
||||
'socle.schema_schema3.databases.password': None,
|
||||
'socle.schema_schema3.databases.user_database_snom.name': None,
|
||||
'socle.schema_schema3.databases.user_database_snom.login': None,
|
||||
'socle.schema_schema3.databases.user_database_snom.password2': None,
|
||||
'socle.schema_schema3.databases.user_database_srem.name': None,
|
||||
'socle.schema_schema3.databases.user_database_srem.login': None,
|
||||
'socle.schema_schema3.databases.user_database_srem.password2': None,
|
||||
'socle.schema_schema3.databases.user_database_srep.name': None,
|
||||
'socle.schema_schema3.databases.user_database_srep.login': None,
|
||||
'socle.schema_schema3.databases.user_database_srep.password2': None,
|
||||
}
|
||||
cfg.option('socle.database_schemas').value.set(['schema1'])
|
||||
# assert cfg.value.get() == {'socle.database_schemas': ['schema1'],
|
||||
# 'socle.schema_schema1.database_names': ['srep',
|
||||
# 'snom',
|
||||
# 'srem'],
|
||||
# 'socle.schema_schema1.databases.password': None,
|
||||
# 'socle.schema_schema1.databases.user_database_snom.name': None,
|
||||
# 'socle.schema_schema1.databases.user_database_snom.login': None,
|
||||
# 'socle.schema_schema1.databases.user_database_snom.password2': None,
|
||||
# 'socle.schema_schema1.databases.user_database_srem.name': None,
|
||||
# 'socle.schema_schema1.databases.user_database_srem.login': None,
|
||||
# 'socle.schema_schema1.databases.user_database_srem.password2': None,
|
||||
# 'socle.schema_schema1.databases.user_database_srep.name': None,
|
||||
# 'socle.schema_schema1.databases.user_database_srep.login': None,
|
||||
# 'socle.schema_schema1.databases.user_database_srep.password2': None,
|
||||
# }
|
||||
|
|
|
|||
|
|
@ -151,18 +151,18 @@ def test_force_default_on_freeze_leader():
|
|||
dummy2 = BoolOption('dummy2', 'Test string option', multi=True)
|
||||
descr = Leadership("dummy1", "", [dummy1, dummy2])
|
||||
od1 = OptionDescription("root", "", [descr])
|
||||
with pytest.raises(ConfigError):
|
||||
Config(od1)
|
||||
# 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)
|
||||
descr = Leadership("dummy1", "", [dummy1, dummy2])
|
||||
od1 = OptionDescription("root", "", [descr])
|
||||
with pytest.raises(ConfigError):
|
||||
Config(od1)
|
||||
#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)
|
||||
# descr = Leadership("dummy1", "", [dummy1, dummy2])
|
||||
# od1 = OptionDescription("root", "", [descr])
|
||||
# with pytest.raises(ConfigError):
|
||||
# Config(od1)
|
||||
# assert not list_sessions()
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -313,8 +313,8 @@ def manager_callback(callback: Callable,
|
|||
# raise PropertiesOptionError (which is catched) because must not add value None in carry_out_calculation
|
||||
if param.notraisepropertyerror or param.raisepropertyerror:
|
||||
raise err from err
|
||||
raise ConfigError(_('unable to carry out a calculation for "{}"'
|
||||
', {}').format(option.impl_get_display_name(), err), err) from err
|
||||
display_name = option_bag.option.impl_get_display_name()
|
||||
raise ConfigError(_('unable to carry out a calculation for "{}", {}').format(display_name, err)) from err
|
||||
except ValueError as err:
|
||||
raise ValueError(_('the option "{0}" is used in a calculation but is invalid ({1})').format(option_bag.option.impl_get_display_name(), err)) from err
|
||||
except AttributeError as err:
|
||||
|
|
@ -324,7 +324,8 @@ def manager_callback(callback: Callable,
|
|||
['configerror'],
|
||||
config_bag.context.get_settings(),
|
||||
)
|
||||
raise ConfigError(_(f'unable to get value for calculating "{option_bag.option.impl_get_display_name()}", {err}')) from err
|
||||
display_name = option_bag.option.impl_get_display_name()
|
||||
raise ConfigError(_(f'unable to get value for calculating "{display_name}", {err}')) from err
|
||||
return value
|
||||
|
||||
def get_option_bag(config_bag,
|
||||
|
|
@ -359,8 +360,8 @@ def manager_callback(callback: Callable,
|
|||
# raise PropertiesOptionError (which is catched) because must not add value None in carry_out_calculation
|
||||
if param.notraisepropertyerror or param.raisepropertyerror:
|
||||
raise err from err
|
||||
raise ConfigError(_('unable to carry out a calculation for "{}"'
|
||||
', {}').format(option.impl_get_display_name(), err), err) from err
|
||||
display_name = option.impl_get_display_name()
|
||||
raise ConfigError(_('unable to carry out a calculation for "{}", {}').format(display_name, err)) from err
|
||||
except ValueError as err:
|
||||
raise ValueError(_('the option "{0}" is used in a calculation but is invalid ({1})').format(option.impl_get_display_name(), err)) from err
|
||||
except AttributeError as err:
|
||||
|
|
@ -370,7 +371,8 @@ def manager_callback(callback: Callable,
|
|||
['configerror'],
|
||||
config_bag.context.get_settings(),
|
||||
)
|
||||
raise ConfigError(_(f'unable to get value for calculating "{option.impl_get_display_name()}", {err}')) from err
|
||||
display_name = option.impl_get_display_name()
|
||||
raise ConfigError(_(f'unable to get value for calculating "{display_name}", {err}')) from err
|
||||
if len(options_bag) > 1:
|
||||
parent_option_bag = options_bag[-2]
|
||||
else:
|
||||
|
|
@ -399,17 +401,17 @@ def manager_callback(callback: Callable,
|
|||
param.default_value,
|
||||
)
|
||||
except ValueError as err:
|
||||
raise ConfigError(_('option "{}" cannot be calculated: {}').format(option.impl_get_display_name(),
|
||||
str(err),
|
||||
))
|
||||
display_name = option.impl_get_display_name()
|
||||
raise ConfigError(_(f'unable to get value for calculating "{display_name}", {err}')) from err
|
||||
|
||||
if isinstance(param, ParamIndex):
|
||||
return index
|
||||
|
||||
if isinstance(param, ParamSuffix):
|
||||
if not option.issubdyn():
|
||||
raise ConfigError(_('option "{}" is not in a dynoptiondescription').format(option.impl_get_display_name()))
|
||||
return option.impl_getsuffix()
|
||||
display_name = option_bag.option.impl_get_display_name()
|
||||
raise ConfigError(_('option "{display_name}" is not in a dynoptiondescription'))
|
||||
return option.get_suffixes()[-1]
|
||||
|
||||
if isinstance(param, ParamSelfOption):
|
||||
value = calc_self(param,
|
||||
|
|
@ -454,13 +456,22 @@ def manager_callback(callback: Callable,
|
|||
found = True
|
||||
elif option.impl_is_sub_dyn_optiondescription():
|
||||
if option.getsubdyn() == callbk_option.getsubdyn():
|
||||
root_path = option.impl_getpath().rsplit('.', 1)[0]
|
||||
len_path = root_path.count('.')
|
||||
full_path = root_path + '.' + callbk_option.impl_getpath().split('.', len_path + 1)[-1]
|
||||
callbk_path = callbk_option.impl_getpath()
|
||||
# callbk_len = callbk_path.count('.') + 1
|
||||
option_path = option.impl_getpath()
|
||||
# option_len = option_path.count('.') + 1
|
||||
# root_len = callbk_len - option_len - 1
|
||||
# root_path = option.impl_getpath().rsplit('.', root_len)[0]
|
||||
#len_path = root_path.count('.')
|
||||
print('===>+', callbk_path, option_path)
|
||||
print('===', option.get_suffixes())
|
||||
full_path = root_path + '.' + callbk_option.impl_getpath().split('.', root_len + 1)[-1]
|
||||
root_option_bag = OptionBag(config_bag.context.get_description(),
|
||||
None,
|
||||
config_bag,
|
||||
)
|
||||
print('===', root_path, root_len, callbk_len, option_len, callbk_path, option_path)
|
||||
print(")))", full_path, option.impl_getpath(), callbk_option.impl_getpath())
|
||||
try:
|
||||
soptions_bag = config_bag.context.get_sub_option_bag(root_option_bag,
|
||||
full_path,
|
||||
|
|
@ -476,21 +487,49 @@ def manager_callback(callback: Callable,
|
|||
elif option.impl_is_dynsymlinkoption():
|
||||
rootpath = option.rootpath
|
||||
call_path = callbk_option.impl_getpath()
|
||||
if option.opt.issubdyn() and callbk_option.getsubdyn() == option.getsubdyn() or \
|
||||
not option.opt.issubdyn() and callbk_option.getsubdyn() == option.opt:
|
||||
# in same dynoption
|
||||
suffix = option.impl_getsuffix()
|
||||
subdyn = callbk_option.getsubdyn()
|
||||
root_path, sub_path = subdyn.split_path(subdyn,
|
||||
option,
|
||||
)
|
||||
if root_path:
|
||||
parent_path = root_path + subdyn.impl_getname(suffix) + sub_path
|
||||
else:
|
||||
parent_path = subdyn.impl_getname(suffix) + sub_path
|
||||
in_same_dyn = False
|
||||
if not option.opt.issubdyn() and callbk_option.getsubdyn() == option.opt:
|
||||
# First dyn
|
||||
in_same_dyn = True
|
||||
elif option.opt.issubdyn():
|
||||
# Search if callback and option has a common subdyn
|
||||
callbk_subdyn = callbk_option.getsubdyn()
|
||||
sub_dyn = option
|
||||
while True:
|
||||
sub_dyn = sub_dyn.getsubdyn()
|
||||
if sub_dyn == callbk_subdyn:
|
||||
in_same_dyn = True
|
||||
break
|
||||
if not sub_dyn.issubdyn():
|
||||
break
|
||||
if in_same_dyn:
|
||||
sub_dyns = []
|
||||
sub_dyn = callbk_option
|
||||
while True:
|
||||
sub_dyn = sub_dyn.getsubdyn()
|
||||
sub_dyns.append(sub_dyn)
|
||||
if not sub_dyn.issubdyn():
|
||||
break
|
||||
suffixes = option.get_suffixes().copy()
|
||||
paths = []
|
||||
option_path = callbk_option.impl_getpath().rsplit('.', 1)[0]
|
||||
idx = len(sub_dyns) - 1
|
||||
for sub_dyn in sub_dyns:
|
||||
dyn_path = sub_dyn.impl_getpath()
|
||||
if dyn_path.count('.') == option_path.count('.'):
|
||||
*root_paths, dyn_path_ = option_path.split('.', dyn_path.count('.') + 1)
|
||||
else:
|
||||
*root_paths, dyn_path_, child_path = option_path.split('.', dyn_path.count('.') + 1)
|
||||
paths.insert(0, child_path)
|
||||
paths.insert(0, sub_dyn.impl_getname(suffixes[idx]))
|
||||
idx -= 1
|
||||
option_path = '.'.join(root_paths)
|
||||
if option_path:
|
||||
paths.insert(0, option_path)
|
||||
parent_path = '.'.join(paths)
|
||||
callbk_option = callbk_option.to_dynoption(parent_path,
|
||||
suffix,
|
||||
subdyn,
|
||||
option.get_suffixes(),
|
||||
sub_dyn,
|
||||
)
|
||||
found = True
|
||||
if not found:
|
||||
|
|
@ -519,8 +558,6 @@ def manager_callback(callback: Callable,
|
|||
else:
|
||||
index_ = None
|
||||
with_index = False
|
||||
if callbk_option.impl_getpath() == 'od.dodval1.st.boolean':
|
||||
raise Exception('pfff')
|
||||
value = get_value(config_bag,
|
||||
callbk_option,
|
||||
param,
|
||||
|
|
@ -602,6 +639,7 @@ def carry_out_calculation(option,
|
|||
kwargs,
|
||||
)
|
||||
if isinstance(ret, list) and not option.impl_is_dynoptiondescription() and \
|
||||
not option.impl_is_optiondescription() and \
|
||||
option.impl_is_follower() and not option.impl_is_submulti():
|
||||
if args or kwargs:
|
||||
raise LeadershipError(_('the "{}" function with positional arguments "{}" '
|
||||
|
|
|
|||
|
|
@ -191,6 +191,7 @@ class _SubConfig:
|
|||
properties=None,
|
||||
))
|
||||
options = sub_options
|
||||
print('===========', options)
|
||||
for doption_bag in options:
|
||||
self.reset_one_option_cache(resetted_opts,
|
||||
doption_bag,
|
||||
|
|
|
|||
|
|
@ -88,6 +88,7 @@ class DynOptionDescription(OptionDescription):
|
|||
|
||||
def get_suffixes(self,
|
||||
config_bag: ConfigBag,
|
||||
*,
|
||||
dynoption=None,
|
||||
) -> List[str]:
|
||||
"""get dynamic suffixes
|
||||
|
|
@ -134,8 +135,9 @@ class DynOptionDescription(OptionDescription):
|
|||
(option.impl_is_sub_dyn_optiondescription() and option.opt == self)
|
||||
|
||||
def split_path(self,
|
||||
dynoption,
|
||||
option,
|
||||
*,
|
||||
dynoption=None,
|
||||
) -> Tuple[str, str]:
|
||||
"""self.impl_getpath() is something like root.xxx.dynoption_path
|
||||
option.impl_getpath() is something like root.xxx.dynoption_path.sub.path
|
||||
|
|
@ -169,8 +171,8 @@ class DynOptionDescription(OptionDescription):
|
|||
properties=undefined,
|
||||
dynoption=None,
|
||||
):
|
||||
root_path, sub_path = self.split_path(dynoption,
|
||||
option,
|
||||
root_path, sub_path = self.split_path(option,
|
||||
dynoption=dynoption,
|
||||
)
|
||||
for suffix in self.get_suffixes(config_bag,
|
||||
dynoption=dynoption,
|
||||
|
|
@ -182,7 +184,7 @@ class DynOptionDescription(OptionDescription):
|
|||
else:
|
||||
parent_path = self.impl_getname(suffix) + sub_path
|
||||
yield OptionBag(option.to_dynoption(parent_path,
|
||||
suffix,
|
||||
[suffix],
|
||||
self,
|
||||
),
|
||||
index,
|
||||
|
|
|
|||
|
|
@ -248,11 +248,11 @@ class Leadership(OptionDescription):
|
|||
|
||||
def to_dynoption(self,
|
||||
rootpath: str,
|
||||
suffix: str,
|
||||
suffixes: Optional[list],
|
||||
ori_dyn,
|
||||
) -> SynDynLeadership:
|
||||
return SynDynLeadership(self,
|
||||
rootpath,
|
||||
suffix,
|
||||
suffixes,
|
||||
ori_dyn,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -464,14 +464,14 @@ class Option(BaseOption):
|
|||
|
||||
def to_dynoption(self,
|
||||
rootpath: str,
|
||||
suffix: str,
|
||||
suffixes: list[str],
|
||||
dyn_parent,
|
||||
) -> SynDynOption:
|
||||
"""tranforme a dynoption to a syndynoption
|
||||
"""
|
||||
return SynDynOption(self,
|
||||
rootpath,
|
||||
suffix,
|
||||
suffixes,
|
||||
dyn_parent,
|
||||
)
|
||||
def validate(self, value: Any):
|
||||
|
|
|
|||
|
|
@ -148,7 +148,7 @@ class CacheOptionDescription(BaseOption):
|
|||
if option.issubdyn():
|
||||
subpath = leader_option_bag.option.rootpath
|
||||
doption = option.to_dynoption(subpath,
|
||||
leader_option_bag.option.impl_getsuffix(),
|
||||
leader_option_bag.option.get_suffixes(),
|
||||
leader_option_bag.option.dyn_parent,
|
||||
)
|
||||
else:
|
||||
|
|
@ -196,7 +196,7 @@ class OptionDescriptionWalk(CacheOptionDescription):
|
|||
subpath: str,
|
||||
*,
|
||||
dynoption=None,
|
||||
option_suffix: Optional[str]=None,
|
||||
option_suffixes: Optional[str]=None,
|
||||
allow_dynoption: bool=False,
|
||||
) -> Union[BaseOption, SynDynOptionDescription]:
|
||||
"""get a child
|
||||
|
|
@ -204,16 +204,13 @@ class OptionDescriptionWalk(CacheOptionDescription):
|
|||
# if not dyn
|
||||
if name in self._children[0]: # pylint: disable=no-member
|
||||
option = self._children[1][self._children[0].index(name)] # pylint: disable=no-member
|
||||
if option.impl_is_dynoptiondescription():
|
||||
if allow_dynoption:
|
||||
option_suffix = None
|
||||
else:
|
||||
raise AttributeError(_(f'unknown option "{name}" '
|
||||
"in root optiondescription (it's a dynamic option)"
|
||||
))
|
||||
if option.impl_is_dynoptiondescription() and not allow_dynoption:
|
||||
raise AttributeError(_(f'unknown option "{name}" '
|
||||
"in root optiondescription (it's a dynamic option)"
|
||||
))
|
||||
if option.issubdyn():
|
||||
return option.to_dynoption(subpath,
|
||||
option_suffix,
|
||||
option_suffixes,
|
||||
option,
|
||||
)
|
||||
return option
|
||||
|
|
@ -222,16 +219,18 @@ class OptionDescriptionWalk(CacheOptionDescription):
|
|||
self_opt = dynoption
|
||||
else:
|
||||
self_opt = self
|
||||
if option_suffixes is None:
|
||||
option_suffixes = []
|
||||
for child in self._children[1]: # pylint: disable=no-member
|
||||
if not child.impl_is_dynoptiondescription():
|
||||
continue
|
||||
for suffix in child.get_suffixes(config_bag,
|
||||
dynoption,
|
||||
dynoption=dynoption,
|
||||
):
|
||||
if name != child.impl_getname(suffix):
|
||||
continue
|
||||
return child.to_dynoption(subpath,
|
||||
suffix,
|
||||
option_suffixes + [suffix],
|
||||
child,
|
||||
)
|
||||
if self.impl_get_group_type() == groups.root: # pylint: disable=no-member
|
||||
|
|
@ -248,7 +247,7 @@ class OptionDescriptionWalk(CacheOptionDescription):
|
|||
dyn: bool=True,
|
||||
#path: Optional[str]=None,
|
||||
dynoption=None,
|
||||
option_suffix: Optional[str]=None,
|
||||
option_suffixes: Optional[list]=None,
|
||||
) -> Union[BaseOption, SynDynOptionDescription]:
|
||||
"""get children
|
||||
"""
|
||||
|
|
@ -263,18 +262,20 @@ class OptionDescriptionWalk(CacheOptionDescription):
|
|||
subpath = ''
|
||||
else:
|
||||
subpath = self_opt.impl_getpath()
|
||||
if option_suffixes is None:
|
||||
option_suffixes = []
|
||||
for child in self._children[1]: # pylint: disable=no-member
|
||||
if dyn and child.impl_is_dynoptiondescription():
|
||||
for suffix in child.get_suffixes(config_bag,
|
||||
dynoption,
|
||||
dynoption=dynoption,
|
||||
):
|
||||
yield child.to_dynoption(subpath,
|
||||
suffix,
|
||||
option_suffixes + [suffix],
|
||||
child,
|
||||
)
|
||||
elif dyn and child.issubdyn() or child.impl_is_dynsymlinkoption():
|
||||
yield child.to_dynoption(subpath,
|
||||
option_suffix,
|
||||
option_suffixes,
|
||||
child,
|
||||
)
|
||||
else:
|
||||
|
|
@ -285,12 +286,16 @@ class OptionDescriptionWalk(CacheOptionDescription):
|
|||
byname: Optional[str],
|
||||
config_bag: ConfigBag,
|
||||
self_opt: BaseOption=None,
|
||||
*,
|
||||
option_suffixes: Optional[list]=None
|
||||
) -> Iterator[Union[BaseOption, SynDynOptionDescription]]:
|
||||
"""get children recursively
|
||||
"""
|
||||
if self_opt is None:
|
||||
self_opt = self
|
||||
for option in self_opt.get_children(config_bag):
|
||||
else:
|
||||
option_suffixes = self_opt.get_suffixes()
|
||||
for option in self_opt.get_children(config_bag, option_suffixes=option_suffixes):
|
||||
if option.impl_is_optiondescription():
|
||||
for subopt in option.get_children_recursively(bytype,
|
||||
byname,
|
||||
|
|
@ -402,18 +407,19 @@ class OptionDescription(OptionDescriptionWalk):
|
|||
|
||||
def to_dynoption(self,
|
||||
rootpath: str,
|
||||
suffix: str,
|
||||
suffixes: Optional[list],
|
||||
ori_dyn) -> SynDynOptionDescription:
|
||||
"""get syn dyn option description
|
||||
"""
|
||||
if suffix is None:
|
||||
if suffixes is None:
|
||||
return SubDynOptionDescription(self,
|
||||
rootpath,
|
||||
suffixes,
|
||||
ori_dyn,
|
||||
)
|
||||
return SynDynOptionDescription(self,
|
||||
rootpath,
|
||||
suffix,
|
||||
suffixes,
|
||||
ori_dyn)
|
||||
|
||||
def impl_is_dynsymlinkoption(self) -> bool:
|
||||
|
|
|
|||
|
|
@ -29,19 +29,19 @@ class SynDynOption:
|
|||
"""
|
||||
__slots__ = ('rootpath',
|
||||
'opt',
|
||||
'suffix',
|
||||
'suffixes',
|
||||
'dyn_parent',
|
||||
'__weakref__')
|
||||
|
||||
def __init__(self,
|
||||
opt: BaseOption,
|
||||
rootpath: str,
|
||||
suffix: str,
|
||||
suffixes: list,
|
||||
dyn_parent,
|
||||
) -> None:
|
||||
self.opt = opt
|
||||
self.rootpath = rootpath
|
||||
self.suffix = suffix
|
||||
self.suffixes = suffixes
|
||||
self.dyn_parent = dyn_parent
|
||||
|
||||
def __getattr__(self,
|
||||
|
|
@ -60,10 +60,10 @@ class SynDynOption:
|
|||
"""
|
||||
return self.opt.impl_get_display_name(self)
|
||||
|
||||
def impl_getsuffix(self) -> str:
|
||||
def get_suffixes(self) -> str:
|
||||
"""get suffix
|
||||
"""
|
||||
return self.suffix
|
||||
return self.suffixes
|
||||
|
||||
def impl_getpath(self) -> str:
|
||||
"""get path
|
||||
|
|
@ -85,6 +85,6 @@ class SynDynOption:
|
|||
if leadership:
|
||||
rootpath = self.rootpath.rsplit('.', 1)[0]
|
||||
return leadership.to_dynoption(rootpath,
|
||||
self.suffix,
|
||||
self.suffixes,
|
||||
self.dyn_parent,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -34,16 +34,21 @@ class SubDynOptionDescription:
|
|||
__slots__ = ('rootpath',
|
||||
'opt',
|
||||
'dyn_parent',
|
||||
'suffixes',
|
||||
'__weakref__',
|
||||
)
|
||||
|
||||
def __init__(self,
|
||||
opt: BaseOption,
|
||||
rootpath: str,
|
||||
suffixes: list,
|
||||
dyn_parent,
|
||||
) -> None:
|
||||
self.opt = opt
|
||||
self.rootpath = rootpath
|
||||
if not suffixes:
|
||||
raise Exception('connard')
|
||||
self.suffixes = suffixes
|
||||
self.dyn_parent = dyn_parent
|
||||
|
||||
def impl_getpath(self) -> str:
|
||||
|
|
@ -86,6 +91,9 @@ class SubDynOptionDescription:
|
|||
def impl_is_dynoptiondescription(self) -> bool:
|
||||
return True
|
||||
|
||||
def get_suffixes(self) -> list:
|
||||
return self.suffixes
|
||||
|
||||
def to_dynoption(self,
|
||||
rootpath: str,
|
||||
suffix: str,
|
||||
|
|
@ -99,17 +107,17 @@ class SynDynOptionDescription:
|
|||
"""
|
||||
__slots__ = ('opt',
|
||||
'rootpath',
|
||||
'_suffix',
|
||||
'_suffixes',
|
||||
'ori_dyn')
|
||||
|
||||
def __init__(self,
|
||||
opt: BaseOption,
|
||||
rootpath: str,
|
||||
suffix: str,
|
||||
suffixes: str,
|
||||
ori_dyn) -> None:
|
||||
self.opt = opt
|
||||
self.rootpath = rootpath
|
||||
self._suffix = suffix
|
||||
self._suffixes = suffixes
|
||||
# For a Leadership inside a DynOptionDescription
|
||||
self.ori_dyn = ori_dyn
|
||||
|
||||
|
|
@ -125,7 +133,7 @@ class SynDynOptionDescription:
|
|||
"""get name
|
||||
"""
|
||||
if self.opt.impl_is_dynoptiondescription():
|
||||
return self.opt.impl_getname(self._suffix)
|
||||
return self.opt.impl_getname(self._suffixes[-1])
|
||||
return self.opt.impl_getname()
|
||||
|
||||
def impl_get_display_name(self) -> str:
|
||||
|
|
@ -136,13 +144,15 @@ class SynDynOptionDescription:
|
|||
def get_children(self,
|
||||
config_bag: ConfigBag,
|
||||
dyn: bool=True,
|
||||
*,
|
||||
option_suffixes=None
|
||||
):
|
||||
# pylint: disable=unused-argument
|
||||
"""get children
|
||||
"""
|
||||
yield from self.opt.get_children(config_bag,
|
||||
dynoption=self,
|
||||
option_suffix=self._suffix,
|
||||
option_suffixes=self._suffixes,
|
||||
)
|
||||
|
||||
def get_child(self,
|
||||
|
|
@ -157,7 +167,7 @@ class SynDynOptionDescription:
|
|||
config_bag,
|
||||
subpath,
|
||||
dynoption=self,
|
||||
option_suffix=self._suffix,
|
||||
option_suffixes=self._suffixes,
|
||||
allow_dynoption=allow_dynoption,
|
||||
)
|
||||
|
||||
|
|
@ -204,10 +214,10 @@ class SynDynOptionDescription:
|
|||
path = f'{self.rootpath}.{path}'
|
||||
return path
|
||||
|
||||
def impl_getsuffix(self) -> str:
|
||||
"""get suffix
|
||||
def get_suffixes(self) -> str:
|
||||
"""get suffixes
|
||||
"""
|
||||
return self._suffix
|
||||
return self._suffixes
|
||||
|
||||
|
||||
class SynDynLeadership(SynDynOptionDescription):
|
||||
|
|
@ -217,7 +227,7 @@ class SynDynLeadership(SynDynOptionDescription):
|
|||
"""get the leader
|
||||
"""
|
||||
return self.opt.get_leader().to_dynoption(self.impl_getpath(),
|
||||
self._suffix,
|
||||
self._suffixes,
|
||||
self.ori_dyn,
|
||||
)
|
||||
|
||||
|
|
@ -227,7 +237,7 @@ class SynDynLeadership(SynDynOptionDescription):
|
|||
subpath = self.impl_getpath()
|
||||
for follower in self.opt.get_followers():
|
||||
yield follower.to_dynoption(subpath,
|
||||
self._suffix,
|
||||
self._suffixes,
|
||||
self.ori_dyn,
|
||||
)
|
||||
|
||||
|
|
@ -271,7 +281,7 @@ class SynDynLeadership(SynDynOptionDescription):
|
|||
dyn=self,
|
||||
)
|
||||
|
||||
def impl_getsuffix(self) -> str:
|
||||
def get_suffixes(self) -> str:
|
||||
"""get suffix
|
||||
"""
|
||||
return self._suffix
|
||||
return self._suffixes
|
||||
|
|
|
|||
|
|
@ -152,12 +152,7 @@ class Values:
|
|||
"""
|
||||
has_calculation = False
|
||||
if isinstance(value, Calculation):
|
||||
try:
|
||||
value = value.execute(option_bag)
|
||||
except ConfigError as err:
|
||||
msg = _(f'error when calculating "{option_bag.option.impl_get_display_name()}": '
|
||||
f'{err} : {option_bag.path}')
|
||||
raise ConfigError(msg) from err
|
||||
value = value.execute(option_bag)
|
||||
has_calculation = True
|
||||
elif isinstance(value, list):
|
||||
# if value is a list, do subcalculation
|
||||
|
|
@ -354,6 +349,7 @@ class Values:
|
|||
for coption in option.get_children_recursively(None,
|
||||
None,
|
||||
option_bag.config_bag,
|
||||
option_suffixes=[],
|
||||
):
|
||||
if 'force_store_value' in coption.impl_getproperties():
|
||||
force_store_options.append(coption)
|
||||
|
|
|
|||
Loading…
Reference in a new issue