feat: identifier could be calculated
This commit is contained in:
parent
9cd46c7c10
commit
e23479ae97
10 changed files with 177 additions and 47 deletions
|
|
@ -1000,19 +1000,17 @@ class ParserVariable:
|
||||||
calculation_object["namespace"] = self.namespace
|
calculation_object["namespace"] = self.namespace
|
||||||
calculation_object["xmlfiles"] = xmlfiles
|
calculation_object["xmlfiles"] = xmlfiles
|
||||||
#
|
#
|
||||||
|
if attribute == "default" and "identifier" in calculation_object:
|
||||||
|
identifier = calculation_object["identifier"]
|
||||||
|
if isinstance(identifier, dict):
|
||||||
|
self.set_calculation(calculation_object, "identifier", identifier, path, family_is_dynamic, xmlfiles, inside_list=inside_list, index=index)
|
||||||
if "params" in calculation_object:
|
if "params" in calculation_object:
|
||||||
if not isinstance(calculation_object["params"], dict):
|
if not isinstance(calculation_object["params"], dict):
|
||||||
raise Exception("params must be a dict")
|
raise Exception("params must be a dict")
|
||||||
params = []
|
params = []
|
||||||
for key, val in calculation_object["params"].items():
|
for key, val in calculation_object["params"].items():
|
||||||
if isinstance(val, dict) and "type" not in val:
|
if isinstance(val, dict) and "type" not in val:
|
||||||
# auto set type
|
self.set_param_type(val)
|
||||||
param_typ = set(CALCULATION_TYPES) & set(val)
|
|
||||||
# XXX variable is also set to information
|
|
||||||
if param_typ == {"variable", "information"}:
|
|
||||||
param_typ = {"information"}
|
|
||||||
if len(param_typ) == 1:
|
|
||||||
val["type"] = list(param_typ)[0]
|
|
||||||
if not isinstance(val, dict) or "type" not in val:
|
if not isinstance(val, dict) or "type" not in val:
|
||||||
param_typ = "any"
|
param_typ = "any"
|
||||||
val = {
|
val = {
|
||||||
|
|
@ -1064,6 +1062,15 @@ class ParserVariable:
|
||||||
else:
|
else:
|
||||||
obj[attribute][index] = calc
|
obj[attribute][index] = calc
|
||||||
|
|
||||||
|
def set_param_type(self, val):
|
||||||
|
# auto set type
|
||||||
|
param_typ = set(CALCULATION_TYPES) & set(val)
|
||||||
|
# XXX variable is also set to information
|
||||||
|
if param_typ == {"variable", "information"}:
|
||||||
|
param_typ = {"information"}
|
||||||
|
if len(param_typ) == 1:
|
||||||
|
val["type"] = list(param_typ)[0]
|
||||||
|
|
||||||
|
|
||||||
class RougailConvert(ParserVariable):
|
class RougailConvert(ParserVariable):
|
||||||
"""Main Rougail conversion"""
|
"""Main Rougail conversion"""
|
||||||
|
|
|
||||||
|
|
@ -81,8 +81,8 @@ def get_convert_option_types():
|
||||||
|
|
||||||
|
|
||||||
class Param(BaseModel):
|
class Param(BaseModel):
|
||||||
key: str
|
key: StrictStr
|
||||||
namespace: Optional[str]
|
namespace: Optional[StrictStr]
|
||||||
model_config = ConfigDict(extra="forbid")
|
model_config = ConfigDict(extra="forbid")
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
|
|
@ -102,13 +102,13 @@ class Param(BaseModel):
|
||||||
|
|
||||||
|
|
||||||
class AnyParam(Param):
|
class AnyParam(Param):
|
||||||
type: str
|
type: StrictStr
|
||||||
value: Union[BASETYPE, List[BASETYPE]]
|
value: Union[BASETYPE, List[BASETYPE]]
|
||||||
|
|
||||||
|
|
||||||
class VariableParam(Param):
|
class VariableParam(Param):
|
||||||
type: str
|
type: StrictStr
|
||||||
variable: str
|
variable: StrictStr
|
||||||
propertyerror: bool = True
|
propertyerror: bool = True
|
||||||
whole: bool = False
|
whole: bool = False
|
||||||
# dynamic: bool = True
|
# dynamic: bool = True
|
||||||
|
|
@ -151,7 +151,7 @@ class VariableParam(Param):
|
||||||
|
|
||||||
|
|
||||||
class IdentifierParam(Param):
|
class IdentifierParam(Param):
|
||||||
type: str
|
type: StrictStr
|
||||||
identifier: Optional[int] = None
|
identifier: Optional[int] = None
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
|
|
@ -167,9 +167,9 @@ class IdentifierParam(Param):
|
||||||
|
|
||||||
|
|
||||||
class InformationParam(Param):
|
class InformationParam(Param):
|
||||||
type: str
|
type: StrictStr
|
||||||
information: str
|
information: StrictStr
|
||||||
variable: Optional[str] = None
|
variable: Optional[StrictStr] = None
|
||||||
|
|
||||||
def to_param(
|
def to_param(
|
||||||
self, attribute_name, objectspace, path, version, namespace, xmlfiles
|
self, attribute_name, objectspace, path, version, namespace, xmlfiles
|
||||||
|
|
@ -202,7 +202,7 @@ class InformationParam(Param):
|
||||||
|
|
||||||
|
|
||||||
class IndexParam(Param):
|
class IndexParam(Param):
|
||||||
type: str
|
type: StrictStr
|
||||||
|
|
||||||
def to_param(
|
def to_param(
|
||||||
self, attribute_name, objectspace, path, version, namespace, xmlfiles
|
self, attribute_name, objectspace, path, version, namespace, xmlfiles
|
||||||
|
|
@ -220,8 +220,8 @@ class IndexParam(Param):
|
||||||
|
|
||||||
|
|
||||||
class NamespaceParam(Param):
|
class NamespaceParam(Param):
|
||||||
type: str
|
type: StrictStr
|
||||||
namespace: str
|
namespace: StrictStr
|
||||||
|
|
||||||
def to_param(
|
def to_param(
|
||||||
self, attribute_name, objectspace, path, version, namespace, xmlfiles
|
self, attribute_name, objectspace, path, version, namespace, xmlfiles
|
||||||
|
|
@ -247,15 +247,15 @@ PARAM_TYPES = {
|
||||||
|
|
||||||
|
|
||||||
class Calculation(BaseModel):
|
class Calculation(BaseModel):
|
||||||
# path: str
|
# path: StrictStr
|
||||||
inside_list: bool
|
inside_list: bool
|
||||||
version: str
|
version: StrictStr
|
||||||
ori_path: Optional[str] = None
|
ori_path: Optional[StrictStr] = None
|
||||||
default_values: Any = None
|
default_values: Any = None
|
||||||
namespace: Optional[str]
|
namespace: Optional[StrictStr]
|
||||||
warnings: Optional[bool] = None
|
warnings: Optional[bool] = None
|
||||||
description: Optional[StrictStr] = None
|
description: Optional[StrictStr] = None
|
||||||
xmlfiles: List[str]
|
xmlfiles: List[StrictStr]
|
||||||
|
|
||||||
model_config = ConfigDict(extra="forbid")
|
model_config = ConfigDict(extra="forbid")
|
||||||
|
|
||||||
|
|
@ -492,6 +492,7 @@ class _VariableCalculation(Calculation):
|
||||||
propertyerror: bool = True,
|
propertyerror: bool = True,
|
||||||
allow_none: bool = False
|
allow_none: bool = False
|
||||||
optional: bool = False
|
optional: bool = False
|
||||||
|
identifier: Optional[Calculation] = None
|
||||||
|
|
||||||
def get_variable(
|
def get_variable(
|
||||||
self,
|
self,
|
||||||
|
|
@ -540,6 +541,15 @@ class _VariableCalculation(Calculation):
|
||||||
variable_in_calculation_identifier: Optional[str],
|
variable_in_calculation_identifier: Optional[str],
|
||||||
key: str = None,
|
key: str = None,
|
||||||
):
|
):
|
||||||
|
identifier_is_a_calculation = False
|
||||||
|
if self.identifier:
|
||||||
|
if variable_in_calculation_identifier:
|
||||||
|
msg = _(
|
||||||
|
'variable "{0}" has an attribute "{1}" with an identifier "{2}" but the path has also the identifier "{3}"'
|
||||||
|
).format(path, self.attribute_name, self.variable, self.identifier, variable_in_calculation_identifier)
|
||||||
|
raise DictConsistencyError(msg, 89, self.xmlfiles)
|
||||||
|
variable_in_calculation_identifier = self.identifier
|
||||||
|
identifier_is_a_calculation = True
|
||||||
if not variable_in_calculation:
|
if not variable_in_calculation:
|
||||||
if not objectspace.force_optional:
|
if not objectspace.force_optional:
|
||||||
msg = _(
|
msg = _(
|
||||||
|
|
@ -564,8 +574,9 @@ class _VariableCalculation(Calculation):
|
||||||
params["__default_value"] = self.default_values
|
params["__default_value"] = self.default_values
|
||||||
if self.allow_none:
|
if self.allow_none:
|
||||||
params["allow_none"] = True
|
params["allow_none"] = True
|
||||||
|
if not identifier_is_a_calculation:
|
||||||
self.check_multi(
|
self.check_multi(
|
||||||
objectspace, path, variable_in_calculation_path, variable_in_calculation
|
objectspace, path, variable_in_calculation_path, variable_in_calculation,
|
||||||
)
|
)
|
||||||
if path in objectspace.followers:
|
if path in objectspace.followers:
|
||||||
multi = objectspace.multis[path] == "submulti"
|
multi = objectspace.multis[path] == "submulti"
|
||||||
|
|
@ -718,7 +729,7 @@ class _VariableCalculation(Calculation):
|
||||||
|
|
||||||
|
|
||||||
class VariableCalculation(_VariableCalculation):
|
class VariableCalculation(_VariableCalculation):
|
||||||
attribute_name: Literal["default", "choices", "dynamic"]
|
attribute_name: Literal["default", "choices", "dynamic", "identifier"]
|
||||||
default: Any = undefined
|
default: Any = undefined
|
||||||
|
|
||||||
def to_function(
|
def to_function(
|
||||||
|
|
@ -1039,7 +1050,7 @@ SECRET_BASETYPE_CALC = Union[StrictStr, JinjaCalculation]
|
||||||
|
|
||||||
|
|
||||||
class Family(BaseModel):
|
class Family(BaseModel):
|
||||||
name: str
|
name: StrictStr
|
||||||
# informations
|
# informations
|
||||||
description: Optional[StrictStr] = None
|
description: Optional[StrictStr] = None
|
||||||
help: Optional[StrictStr] = None
|
help: Optional[StrictStr] = None
|
||||||
|
|
@ -1060,12 +1071,12 @@ class Family(BaseModel):
|
||||||
|
|
||||||
class Dynamic(Family):
|
class Dynamic(Family):
|
||||||
# None only for format 1.0
|
# None only for format 1.0
|
||||||
variable: str = None
|
variable: StrictStr = None
|
||||||
dynamic: Union[List[Union[StrictStr, Calculation]], Calculation]
|
dynamic: Union[List[Union[StrictStr, Calculation]], Calculation]
|
||||||
|
|
||||||
|
|
||||||
class Variable(BaseModel):
|
class Variable(BaseModel):
|
||||||
name: str
|
name: StrictStr
|
||||||
# user informations
|
# user informations
|
||||||
description: Optional[StrictStr] = None
|
description: Optional[StrictStr] = None
|
||||||
help: Optional[StrictStr] = None
|
help: Optional[StrictStr] = None
|
||||||
|
|
@ -1075,7 +1086,7 @@ class Variable(BaseModel):
|
||||||
test: Optional[list] = None
|
test: Optional[list] = None
|
||||||
# validations
|
# validations
|
||||||
## type will be set dynamically in `annotator/value.py`, default is None
|
## type will be set dynamically in `annotator/value.py`, default is None
|
||||||
type: str = None
|
type: StrictStr = None
|
||||||
params: Optional[List[Param]] = None
|
params: Optional[List[Param]] = None
|
||||||
regexp: Optional[StrictStr] = None
|
regexp: Optional[StrictStr] = None
|
||||||
choices: Optional[Union[List[BASETYPE_CALC], Calculation]] = None
|
choices: Optional[Union[List[BASETYPE_CALC], Calculation]] = None
|
||||||
|
|
@ -1094,21 +1105,21 @@ class Variable(BaseModel):
|
||||||
disabled: Union[bool, Calculation] = False
|
disabled: Union[bool, Calculation] = False
|
||||||
frozen: Union[bool, Calculation] = False
|
frozen: Union[bool, Calculation] = False
|
||||||
# others
|
# others
|
||||||
path: str
|
path: StrictStr
|
||||||
namespace: Optional[str]
|
namespace: Optional[StrictStr]
|
||||||
version: str
|
version: StrictStr
|
||||||
xmlfiles: List[str] = []
|
xmlfiles: List[StrictStr] = []
|
||||||
|
|
||||||
model_config = ConfigDict(extra="forbid", arbitrary_types_allowed=True)
|
model_config = ConfigDict(extra="forbid", arbitrary_types_allowed=True)
|
||||||
|
|
||||||
|
|
||||||
class SymLink(BaseModel):
|
class SymLink(BaseModel):
|
||||||
type: Literal["symlink"] = "symlink"
|
type: Literal["symlink"] = "symlink"
|
||||||
name: str
|
name: StrictStr
|
||||||
path: str
|
path: StrictStr
|
||||||
opt: Variable
|
opt: Variable
|
||||||
namespace: Optional[str]
|
namespace: Optional[StrictStr]
|
||||||
version: str
|
version: StrictStr
|
||||||
xmlfiles: List[str] = []
|
xmlfiles: List[StrictStr] = []
|
||||||
|
|
||||||
model_config = ConfigDict(extra="forbid")
|
model_config = ConfigDict(extra="forbid")
|
||||||
|
|
|
||||||
|
|
@ -362,12 +362,16 @@ class Common:
|
||||||
)
|
)
|
||||||
raise DictConsistencyError(msg, 49, self.elt.xmlfiles)
|
raise DictConsistencyError(msg, 49, self.elt.xmlfiles)
|
||||||
param_type = "ParamDynOption"
|
param_type = "ParamDynOption"
|
||||||
|
if isinstance(identifier, Calculation):
|
||||||
|
identifiers = self.populate_calculation(identifier)
|
||||||
|
else:
|
||||||
identifiers = []
|
identifiers = []
|
||||||
for ident in identifier:
|
for ident in identifier:
|
||||||
if isinstance(ident, str):
|
if isinstance(ident, str):
|
||||||
ident = self.convert_str(ident)
|
ident = self.convert_str(ident)
|
||||||
identifiers.append(str(ident))
|
identifiers.append(str(ident))
|
||||||
params.append("[" + ", ".join(identifiers) + "]")
|
identifiers = "[" + ", ".join(identifiers) + "]"
|
||||||
|
params.append(identifiers)
|
||||||
if param.get("optional", False):
|
if param.get("optional", False):
|
||||||
params.append("optional=True")
|
params.append("optional=True")
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
{
|
||||||
|
"rougail.var1": {
|
||||||
|
"owner": "default",
|
||||||
|
"value": [
|
||||||
|
"val1",
|
||||||
|
"val2"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"rougail.var2": {
|
||||||
|
"owner": "default",
|
||||||
|
"value": "val1"
|
||||||
|
},
|
||||||
|
"rougail.dynval1.var": {
|
||||||
|
"owner": "default",
|
||||||
|
"value": "val1"
|
||||||
|
},
|
||||||
|
"rougail.dynval2.var": {
|
||||||
|
"owner": "default",
|
||||||
|
"value": "val2"
|
||||||
|
},
|
||||||
|
"rougail.var3": {
|
||||||
|
"owner": "default",
|
||||||
|
"value": "val1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"rougail.var1": [
|
||||||
|
"val1",
|
||||||
|
"val2"
|
||||||
|
],
|
||||||
|
"rougail.var2": "val1",
|
||||||
|
"rougail.dynval1.var": "val1",
|
||||||
|
"rougail.dynval2.var": "val2",
|
||||||
|
"rougail.var3": "val1"
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
{
|
||||||
|
"rougail.var1": {
|
||||||
|
"owner": "default",
|
||||||
|
"value": [
|
||||||
|
"val1",
|
||||||
|
"val2"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"rougail.var2": {
|
||||||
|
"owner": "default",
|
||||||
|
"value": "val1"
|
||||||
|
},
|
||||||
|
"rougail.dynval1.var": {
|
||||||
|
"owner": "default",
|
||||||
|
"value": "val1"
|
||||||
|
},
|
||||||
|
"rougail.dynval2.var": {
|
||||||
|
"owner": "default",
|
||||||
|
"value": "val2"
|
||||||
|
},
|
||||||
|
"rougail.var3": {
|
||||||
|
"owner": "default",
|
||||||
|
"value": "val1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
[]
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"rougail.var1": [
|
||||||
|
"val1",
|
||||||
|
"val2"
|
||||||
|
],
|
||||||
|
"rougail.var2": "val1",
|
||||||
|
"rougail.dynval1.var": "val1",
|
||||||
|
"rougail.dynval2.var": "val2",
|
||||||
|
"rougail.var3": "val1"
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
from tiramisu import *
|
||||||
|
from tiramisu.setting import ALLOWED_LEADER_PROPERTIES
|
||||||
|
from re import compile as re_compile
|
||||||
|
from rougail.tiramisu import func, dict_env, load_functions, ConvertDynOptionDescription
|
||||||
|
load_functions('../rougail-tests/funcs/test.py')
|
||||||
|
try:
|
||||||
|
groups.namespace
|
||||||
|
except:
|
||||||
|
groups.addgroup('namespace')
|
||||||
|
ALLOWED_LEADER_PROPERTIES.add("basic")
|
||||||
|
ALLOWED_LEADER_PROPERTIES.add("standard")
|
||||||
|
ALLOWED_LEADER_PROPERTIES.add("advanced")
|
||||||
|
option_2 = StrOption(name="var1", doc="A suffix variable", multi=True, default=["val1", "val2"], default_multi="val1", properties=frozenset({"mandatory", "standard"}), informations={'ymlfiles': ['../rougail-tests/structures/60_5family_dynamic_calc_identifier/rougail/00-base.yml'], 'type': 'string'})
|
||||||
|
option_3 = StrOption(name="var2", doc="A suffix variable2", default="val1", properties=frozenset({"mandatory", "standard"}), informations={'ymlfiles': ['../rougail-tests/structures/60_5family_dynamic_calc_identifier/rougail/00-base.yml'], 'type': 'string'})
|
||||||
|
option_5 = StrOption(name="var", doc="A dynamic variable", default=Calculation(func['calc_value'], Params((ParamIdentifier()))), properties=frozenset({"mandatory", "standard"}), informations={'ymlfiles': ['../rougail-tests/structures/60_5family_dynamic_calc_identifier/rougail/00-base.yml'], 'type': 'string'})
|
||||||
|
optiondescription_4 = ConvertDynOptionDescription(name="dyn{{ identifier }}", doc="dyn{{ identifier }}", identifiers=Calculation(func['calc_value'], Params((ParamOption(option_2)))), children=[option_5], properties=frozenset({"standard"}), informations={'dynamic_variable': 'rougail.var1', 'ymlfiles': ['../rougail-tests/structures/60_5family_dynamic_calc_identifier/rougail/00-base.yml']})
|
||||||
|
option_6 = StrOption(name="var3", doc="A variable calculated", default=Calculation(func['calc_value'], Params((ParamDynOption(option_5, Calculation(func['calc_value'], Params((ParamOption(option_3)))))))), properties=frozenset({"mandatory", "standard"}), informations={'ymlfiles': ['../rougail-tests/structures/60_5family_dynamic_calc_identifier/rougail/00-base.yml'], 'type': 'string'})
|
||||||
|
optiondescription_1 = OptionDescription(name="rougail", doc="Rougail", group_type=groups.namespace, children=[option_2, option_3, optiondescription_4, option_6], properties=frozenset({"standard"}))
|
||||||
|
option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[optiondescription_1])
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
from tiramisu import *
|
||||||
|
from tiramisu.setting import ALLOWED_LEADER_PROPERTIES
|
||||||
|
from re import compile as re_compile
|
||||||
|
from rougail.tiramisu import func, dict_env, load_functions, ConvertDynOptionDescription
|
||||||
|
load_functions('../rougail-tests/funcs/test.py')
|
||||||
|
try:
|
||||||
|
groups.namespace
|
||||||
|
except:
|
||||||
|
groups.addgroup('namespace')
|
||||||
|
ALLOWED_LEADER_PROPERTIES.add("basic")
|
||||||
|
ALLOWED_LEADER_PROPERTIES.add("standard")
|
||||||
|
ALLOWED_LEADER_PROPERTIES.add("advanced")
|
||||||
|
option_1 = StrOption(name="var1", doc="A suffix variable", multi=True, default=["val1", "val2"], default_multi="val1", properties=frozenset({"mandatory", "standard"}), informations={'ymlfiles': ['../rougail-tests/structures/60_5family_dynamic_calc_identifier/rougail/00-base.yml'], 'type': 'string'})
|
||||||
|
option_2 = StrOption(name="var2", doc="A suffix variable2", default="val1", properties=frozenset({"mandatory", "standard"}), informations={'ymlfiles': ['../rougail-tests/structures/60_5family_dynamic_calc_identifier/rougail/00-base.yml'], 'type': 'string'})
|
||||||
|
option_4 = StrOption(name="var", doc="A dynamic variable", default=Calculation(func['calc_value'], Params((ParamIdentifier()))), properties=frozenset({"mandatory", "standard"}), informations={'ymlfiles': ['../rougail-tests/structures/60_5family_dynamic_calc_identifier/rougail/00-base.yml'], 'type': 'string'})
|
||||||
|
optiondescription_3 = ConvertDynOptionDescription(name="dyn{{ identifier }}", doc="dyn{{ identifier }}", identifiers=Calculation(func['calc_value'], Params((ParamOption(option_1)))), children=[option_4], properties=frozenset({"standard"}), informations={'dynamic_variable': 'var1', 'ymlfiles': ['../rougail-tests/structures/60_5family_dynamic_calc_identifier/rougail/00-base.yml']})
|
||||||
|
option_5 = StrOption(name="var3", doc="A variable calculated", default=Calculation(func['calc_value'], Params((ParamDynOption(option_4, Calculation(func['calc_value'], Params((ParamOption(option_2)))))))), properties=frozenset({"mandatory", "standard"}), informations={'ymlfiles': ['../rougail-tests/structures/60_5family_dynamic_calc_identifier/rougail/00-base.yml'], 'type': 'string'})
|
||||||
|
option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[option_1, option_2, optiondescription_3, option_5])
|
||||||
Loading…
Reference in a new issue