reorganize tiramisureflector
This commit is contained in:
@ -4,7 +4,8 @@ from .group import GroupAnnotator
|
||||
from .service import ServiceAnnotator, ERASED_ATTRIBUTES
|
||||
from .variable import VariableAnnotator, CONVERT_OPTION
|
||||
from .check import CheckAnnotator
|
||||
from .condition import Conditionnnotator
|
||||
from .value import ValueAnnotator
|
||||
from .condition import ConditionAnnotator
|
||||
from .fill import FillAnnotator
|
||||
from .family import FamilyAnnotator, modes
|
||||
from .property import PropertyAnnotator
|
||||
@ -20,12 +21,13 @@ class SpaceAnnotator: # pylint: disable=R0903
|
||||
CheckAnnotator(objectspace,
|
||||
eosfunc_file,
|
||||
)
|
||||
Conditionnnotator(objectspace)
|
||||
ConditionAnnotator(objectspace)
|
||||
FillAnnotator(objectspace,
|
||||
eosfunc_file,
|
||||
)
|
||||
FamilyAnnotator(objectspace)
|
||||
PropertyAnnotator(objectspace)
|
||||
ValueAnnotator(objectspace)
|
||||
|
||||
|
||||
__all__ = ('SpaceAnnotator', 'ERASED_ATTRIBUTES', 'CONVERT_OPTION', 'modes')
|
||||
|
@ -129,7 +129,7 @@ class CheckAnnotator:
|
||||
# value for choice's variable is mandatory
|
||||
variable.mandatory = True
|
||||
# build choice
|
||||
variable.choice = []
|
||||
variable.values = []
|
||||
variable_type = variable.type
|
||||
variable.type = 'choice'
|
||||
|
||||
@ -182,7 +182,7 @@ class CheckAnnotator:
|
||||
choice = self.objectspace.choice(variable.xmlfiles)
|
||||
choice.name = value
|
||||
choice.type = param_type
|
||||
variable.choice.append(choice)
|
||||
variable.values.append(choice)
|
||||
|
||||
if has_variable:
|
||||
return None
|
||||
@ -223,7 +223,7 @@ class CheckAnnotator:
|
||||
msg = _(f'unknown parameter "{param.name}" in check "valid_entier" '
|
||||
f'for variable "{check.target.name}" in {xmlfiles}')
|
||||
raise DictConsistencyError(msg, 19)
|
||||
else:
|
||||
if not hasattr(check.target, 'check'):
|
||||
check.target.check = []
|
||||
check.target.check.append(check)
|
||||
continue
|
||||
if not hasattr(check.target, 'validators'):
|
||||
check.target.validators = []
|
||||
check.target.validators.append(check)
|
||||
|
@ -10,7 +10,7 @@ from ..config import Config
|
||||
FREEZE_AUTOFREEZE_VARIABLE = 'module_instancie'
|
||||
|
||||
|
||||
class Conditionnnotator:
|
||||
class ConditionAnnotator:
|
||||
"""Annotate condition
|
||||
"""
|
||||
def __init__(self,
|
||||
@ -290,6 +290,6 @@ class Conditionnnotator:
|
||||
prop.source = condition.source
|
||||
prop.expected = text
|
||||
prop.name = action
|
||||
if not hasattr(obj, 'property'):
|
||||
obj.property = []
|
||||
obj.property.append(prop)
|
||||
if not hasattr(obj, 'properties'):
|
||||
obj.properties = []
|
||||
obj.properties.append(prop)
|
||||
|
@ -2,6 +2,8 @@
|
||||
"""
|
||||
from ..i18n import _
|
||||
from ..error import DictConsistencyError
|
||||
from ..utils import normalize_family
|
||||
from .variable import RENAME_ATTIBUTES
|
||||
|
||||
|
||||
#mode order is important
|
||||
@ -34,14 +36,28 @@ class FamilyAnnotator:
|
||||
objectspace,
|
||||
):
|
||||
self.objectspace = objectspace
|
||||
if hasattr(self.objectspace.space, 'variables'):
|
||||
self.remove_empty_families()
|
||||
self.change_variable_mode()
|
||||
self.change_family_mode()
|
||||
self.dynamic_families()
|
||||
self.convert_help()
|
||||
if not hasattr(self.objectspace.space, 'variables'):
|
||||
return
|
||||
self.family_names()
|
||||
self.remove_empty_families()
|
||||
self.change_variable_mode()
|
||||
self.change_family_mode()
|
||||
self.dynamic_families()
|
||||
self.convert_help()
|
||||
|
||||
def remove_empty_families(self):
|
||||
def family_names(self) -> None:
|
||||
for families in self.objectspace.space.variables.values():
|
||||
families.doc = families.name
|
||||
families.path = families.name
|
||||
for family in families.family.values():
|
||||
if not hasattr(family, 'description'):
|
||||
family.description = family.name
|
||||
for key, value in RENAME_ATTIBUTES.items():
|
||||
setattr(family, value, getattr(family, key))
|
||||
setattr(family, key, None)
|
||||
family.name = normalize_family(family.name)
|
||||
|
||||
def remove_empty_families(self) -> None:
|
||||
"""Remove all families without any variable
|
||||
"""
|
||||
for families in self.objectspace.space.variables.values():
|
||||
|
@ -26,25 +26,27 @@ class PropertyAnnotator:
|
||||
) -> None:
|
||||
"""convert properties
|
||||
"""
|
||||
properties = []
|
||||
if not hasattr(variable, 'properties'):
|
||||
variable.properties = []
|
||||
|
||||
for prop in PROPERTIES:
|
||||
if hasattr(variable, prop):
|
||||
if getattr(variable, prop) is True:
|
||||
for subprop in CONVERT_PROPERTIES.get(prop, [prop]):
|
||||
properties.append(subprop)
|
||||
variable.properties.append(subprop)
|
||||
setattr(variable, prop, None)
|
||||
if hasattr(variable, 'mode') and variable.mode:
|
||||
properties.append(variable.mode)
|
||||
variable.properties.append(variable.mode)
|
||||
variable.mode = None
|
||||
if 'force_store_value' in properties and \
|
||||
'force_default_on_freeze' in properties: # pragma: no cover
|
||||
if 'force_store_value' in variable.properties and \
|
||||
'force_default_on_freeze' in variable.properties: # pragma: no cover
|
||||
# should not appened
|
||||
xmlfiles = self.objectspace.display_xmlfiles(variable.xmlfiles)
|
||||
msg = _('cannot have auto_freeze or auto_store with the hidden '
|
||||
f'variable "{variable.name}" in {xmlfiles}')
|
||||
raise DictConsistencyError(msg, 50)
|
||||
if properties:
|
||||
variable.properties = set(properties)
|
||||
if not variable.properties:
|
||||
del variable.properties
|
||||
|
||||
def convert_services(self) -> None:
|
||||
"""convert services
|
||||
|
@ -183,10 +183,7 @@ class ServiceAnnotator:
|
||||
variable.multi = None
|
||||
else:
|
||||
variable.doc = key
|
||||
val = self.objectspace.value(xmlfiles)
|
||||
val.type = type_
|
||||
val.name = value
|
||||
variable.value = [val]
|
||||
variable.default = value
|
||||
variable.namespace = 'services'
|
||||
self.objectspace.paths.add_variable('services',
|
||||
path,
|
||||
|
46
src/rougail/annotator/value.py
Normal file
46
src/rougail/annotator/value.py
Normal file
@ -0,0 +1,46 @@
|
||||
class ValueAnnotator:
|
||||
"""Annotate check
|
||||
"""
|
||||
def __init__(self,
|
||||
objectspace,
|
||||
) -> None:
|
||||
if not hasattr(objectspace.space, 'variables'):
|
||||
return
|
||||
self.objectspace = objectspace
|
||||
self.convert_value()
|
||||
|
||||
def convert_value(self) -> None:
|
||||
for families in self.objectspace.space.variables.values():
|
||||
for family in families.family.values():
|
||||
for variable in family.variable.values():
|
||||
if isinstance(variable, self.objectspace.leadership):
|
||||
variable_type = 'leader'
|
||||
for follower in variable.variable:
|
||||
self._convert_value(follower,
|
||||
variable_type,
|
||||
)
|
||||
variable_type = 'follower'
|
||||
else:
|
||||
self._convert_value(variable)
|
||||
|
||||
def _convert_value(self,
|
||||
variable,
|
||||
variable_type: str=None,
|
||||
) -> None:
|
||||
if not hasattr(variable, 'value'):
|
||||
return
|
||||
if variable.value[0].type == 'calculation':
|
||||
variable.default = variable.value[0]
|
||||
else:
|
||||
if variable.multi:
|
||||
if variable_type != 'follower':
|
||||
variable.default = [value.name for value in variable.value]
|
||||
if variable_type != 'leader':
|
||||
if variable.multi == 'submulti':
|
||||
variable.default_multi = [value.name for value in variable.value]
|
||||
else:
|
||||
#FIXME 0 ou -1 ?
|
||||
variable.default_multi = variable.value[-1].name
|
||||
else:
|
||||
variable.default = variable.value[0].name
|
||||
del variable.value
|
@ -1,6 +1,5 @@
|
||||
"""Annotate variable
|
||||
"""
|
||||
from ..utils import normalize_family
|
||||
|
||||
|
||||
CONVERT_OPTION = {'number': dict(opttype="IntOption", func=int),
|
||||
@ -60,15 +59,7 @@ class VariableAnnotator: # pylint: disable=R0903
|
||||
"""convert variable
|
||||
"""
|
||||
for families in self.objectspace.space.variables.values():
|
||||
families.doc = families.name
|
||||
families.path = families.name
|
||||
for family in families.family.values():
|
||||
if not hasattr(family, 'description'):
|
||||
family.description = family.name
|
||||
for key, value in RENAME_ATTIBUTES.items():
|
||||
setattr(family, value, getattr(family, key))
|
||||
setattr(family, key, None)
|
||||
family.name = normalize_family(family.name)
|
||||
if not hasattr(family, 'variable'):
|
||||
continue
|
||||
for variable in family.variable.values():
|
||||
@ -192,9 +183,8 @@ class VariableAnnotator: # pylint: disable=R0903
|
||||
else:
|
||||
self._convert_help(variable)
|
||||
|
||||
def _convert_help(self,
|
||||
variable,
|
||||
) -> None:
|
||||
@staticmethod
|
||||
def _convert_help(variable) -> None:
|
||||
if hasattr(variable, 'help'):
|
||||
variable.information.help = variable.help
|
||||
del variable.help
|
||||
|
@ -7,7 +7,7 @@ from .objspace import RootRougailObject
|
||||
|
||||
|
||||
FUNC_TO_DICT = []
|
||||
ATTRIBUTES_ORDER = ('name', 'doc', 'default', 'multi', 'properties', 'min_number', 'max_number')
|
||||
ATTRIBUTES_ORDER = ('name', 'doc', 'default', 'values', 'multi', 'default_multi', 'properties', 'validators', 'min_number', 'max_number')
|
||||
|
||||
|
||||
class Root(): # pylint: disable=R0903
|
||||
@ -127,6 +127,7 @@ class TiramisuReflector:
|
||||
self.set_name(elt)
|
||||
family.add(Variable(elt,
|
||||
self.text,
|
||||
self.objectspace,
|
||||
is_follower,
|
||||
is_leader,
|
||||
))
|
||||
@ -168,18 +169,19 @@ class Common:
|
||||
f"'expected': ParamValue('{child.expected}')")
|
||||
if child.inverse:
|
||||
kwargs += ", 'reverse_condition': ParamValue(True)"
|
||||
prop = 'Calculation(calc_value, Params(' + action + ', kwargs={' + kwargs + '}))'
|
||||
if self.attrib['properties']:
|
||||
self.attrib['properties'] += ', '
|
||||
self.attrib['properties'] += prop
|
||||
return 'Calculation(calc_value, Params(' + action + ', kwargs={' + kwargs + '}))'
|
||||
|
||||
def properties_to_string(self):
|
||||
"""Change properties to string
|
||||
"""
|
||||
if not self.attrib['properties']:
|
||||
self.attrib['properties'] = ''
|
||||
else:
|
||||
self.attrib['properties'] = "'" + "', '".join(sorted(self.attrib['properties'])) + "'"
|
||||
properties = []
|
||||
calc_properties = []
|
||||
for property_ in self.attrib['properties']:
|
||||
if not isinstance(property_, str):
|
||||
calc_properties.append(self.populate_properties(property_))
|
||||
else:
|
||||
properties.append(f"'{property_}'")
|
||||
return 'frozenset({' + ', '.join(sorted(properties) + calc_properties) + '})'
|
||||
|
||||
def get_attrib(self):
|
||||
"""Get attributes
|
||||
@ -189,13 +191,21 @@ class Common:
|
||||
if value is None:
|
||||
continue
|
||||
if key == 'properties':
|
||||
if not self.attrib[key]:
|
||||
continue
|
||||
value = "frozenset({" + self.attrib[key] + "})"
|
||||
elif key in ['default', 'multi', 'suffixes', 'validators', 'values']:
|
||||
value = self.attrib[key]
|
||||
value = self.properties_to_string()
|
||||
elif key == 'validators':
|
||||
value = '[' + ', '.join([self.calculation_value(val, ['ParamSelfOption()']) for val in value]) + ']'
|
||||
elif key == 'values':
|
||||
if value[0].type == 'calculation':
|
||||
value = value[0].name.reflector_object.get()
|
||||
value = f"Calculation(func.calc_value, Params((ParamOption({value}))))"
|
||||
else:
|
||||
value = str(tuple([val.name for val in value]))
|
||||
elif key in ['multi', 'suffixes']:
|
||||
pass
|
||||
elif isinstance(value, str) and key != 'opt' and not value.startswith('['):
|
||||
value = "'" + value.replace("'", "\\\'") + "'"
|
||||
elif isinstance(value, self.objectspace.value):
|
||||
value = self.calculation_value(value, [])
|
||||
ret_list.append(f'{key}={value}')
|
||||
return ', '.join(ret_list)
|
||||
|
||||
@ -211,22 +221,12 @@ class Common:
|
||||
value = '"' + value.replace('"', '\"') + '"'
|
||||
self.text.append(f'{self.option_name}.impl_set_information("{key}", {value})')
|
||||
|
||||
@staticmethod
|
||||
def get_attributes(space):
|
||||
"""Get attributes
|
||||
def populate_attrib(self):
|
||||
"""Populate attributes
|
||||
"""
|
||||
for attr in ATTRIBUTES_ORDER:
|
||||
if hasattr(space, attr):
|
||||
yield attr
|
||||
|
||||
@staticmethod
|
||||
def get_children(space):
|
||||
"""Get children
|
||||
"""
|
||||
for attr in dir(space):
|
||||
if not attr.startswith('_') and attr not in ERASED_ATTRIBUTES:
|
||||
if isinstance(getattr(space, attr), list):
|
||||
yield attr, getattr(space, attr)
|
||||
if hasattr(self.elt, attr):
|
||||
self.attrib[attr] = getattr(self.elt, attr)
|
||||
|
||||
|
||||
class Variable(Common):
|
||||
@ -235,18 +235,17 @@ class Variable(Common):
|
||||
def __init__(self,
|
||||
elt,
|
||||
text,
|
||||
objectspace,
|
||||
is_follower,
|
||||
is_leader,
|
||||
):
|
||||
super().__init__(elt, text)
|
||||
self.objectspace = objectspace
|
||||
self.is_leader = is_leader
|
||||
self.is_follower = is_follower
|
||||
convert_option = CONVERT_OPTION[elt.type]
|
||||
self.object_type = convert_option['opttype']
|
||||
self.attrib.update(convert_option.get('initkwargs', {}))
|
||||
if self.object_type != 'SymLinkOption':
|
||||
self.attrib['properties'] = []
|
||||
self.attrib['validators'] = []
|
||||
|
||||
def get(self):
|
||||
"""Get tiramisu's object
|
||||
@ -255,79 +254,12 @@ class Variable(Common):
|
||||
self.populate_attrib()
|
||||
if self.object_type == 'SymLinkOption':
|
||||
self.attrib['opt'] = self.elt.opt.reflector_object.get()
|
||||
else:
|
||||
self.parse_children()
|
||||
attrib = self.get_attrib()
|
||||
self.option_name = self.elt.reflector_name
|
||||
self.text.append(f'{self.option_name} = {self.object_type}({attrib})')
|
||||
self.populate_informations()
|
||||
return self.option_name
|
||||
|
||||
def populate_attrib(self):
|
||||
"""Populate attributes
|
||||
"""
|
||||
for key in self.get_attributes(self.elt):
|
||||
self.attrib[key] = getattr(self.elt, key)
|
||||
|
||||
def parse_children(self):
|
||||
"""Parse children
|
||||
"""
|
||||
if 'default' not in self.attrib or self.attrib['multi']:
|
||||
self.attrib['default'] = []
|
||||
if self.attrib['multi'] == 'submulti' and self.is_follower:
|
||||
self.attrib['default_multi'] = []
|
||||
choices = []
|
||||
self.properties_to_string()
|
||||
for tag, children in self.get_children(self.elt):
|
||||
for child in children:
|
||||
self.parse_child(tag,
|
||||
child,
|
||||
choices,
|
||||
)
|
||||
if choices:
|
||||
self.attrib['values'] = str(tuple(choices))
|
||||
if not self.attrib['default']:
|
||||
del self.attrib['default']
|
||||
elif not self.attrib['multi'] and isinstance(self.attrib['default'], list):
|
||||
self.attrib['default'] = self.attrib['default'][-1]
|
||||
if not self.attrib['validators']:
|
||||
del self.attrib['validators']
|
||||
else:
|
||||
self.attrib['validators'] = '[' + ', '.join(self.attrib['validators']) + ']'
|
||||
|
||||
def parse_child(self,
|
||||
tag,
|
||||
child,
|
||||
choices,
|
||||
) -> None:
|
||||
"""Parse child
|
||||
"""
|
||||
if tag == 'property':
|
||||
self.populate_properties(child)
|
||||
elif tag == 'value':
|
||||
self.populate_value(child)
|
||||
elif tag == 'check':
|
||||
validator = self.calculation_value(child, ['ParamSelfOption()'])
|
||||
self.attrib['validators'].append(validator)
|
||||
elif tag == 'choice':
|
||||
self.calculate_choice(child,
|
||||
choices,
|
||||
)
|
||||
else: # pragma: no cover
|
||||
raise Exception(f'unknown tag {tag}')
|
||||
|
||||
def calculate_choice(self,
|
||||
child,
|
||||
choices: list,
|
||||
) -> None:
|
||||
"""Calculating choice
|
||||
"""
|
||||
if child.type == 'calculation':
|
||||
value = child.name.reflector_object.get()
|
||||
self.attrib['values'] = f"Calculation(func.calc_value, Params((ParamOption({value}))))"
|
||||
else:
|
||||
choices.append(child.name)
|
||||
|
||||
def calculation_value(self,
|
||||
child,
|
||||
args,
|
||||
@ -375,28 +307,6 @@ class Variable(Common):
|
||||
return 'ParamSuffix()'
|
||||
return '' # pragma: no cover
|
||||
|
||||
def populate_value(self,
|
||||
child,
|
||||
):
|
||||
"""Populate variable's values
|
||||
"""
|
||||
if child.type == 'calculation':
|
||||
self.attrib['default'] = self.calculation_value(child, [])
|
||||
else:
|
||||
value = child.name
|
||||
if self.attrib['multi'] == 'submulti':
|
||||
self.attrib['default_multi'].append(value)
|
||||
elif self.is_follower:
|
||||
self.attrib['default_multi'] = value
|
||||
elif self.attrib['multi']:
|
||||
self.attrib['default'].append(value)
|
||||
if not self.is_leader:
|
||||
self.attrib['default_multi'] = value
|
||||
elif isinstance(value, (int, float)) or value is None:
|
||||
self.attrib['default'].append(value)
|
||||
else:
|
||||
self.attrib['default'].append("'" + value + "'")
|
||||
|
||||
@staticmethod
|
||||
def build_param(param) -> str:
|
||||
"""build variable parameters
|
||||
@ -431,7 +341,6 @@ class Family(Common):
|
||||
"""
|
||||
if not self.option_name:
|
||||
self.populate_attrib()
|
||||
self.parse_properties()
|
||||
self.populate_dynamic()
|
||||
self.option_name = self.elt.reflector_name
|
||||
object_name = self.get_object_name()
|
||||
@ -448,21 +357,6 @@ class Family(Common):
|
||||
dyn = self.elt.dynamic.reflector_object.get()
|
||||
self.attrib['suffixes'] = f"Calculation(func.calc_value, Params((ParamOption({dyn}))))"
|
||||
|
||||
def populate_attrib(self):
|
||||
"""parse a populate attributes
|
||||
"""
|
||||
for key in self.get_attributes(self.elt):
|
||||
self.attrib[key] = getattr(self.elt, key)
|
||||
|
||||
def parse_properties(self):
|
||||
"""parse current children
|
||||
"""
|
||||
if 'properties' in self.attrib:
|
||||
self.properties_to_string()
|
||||
if hasattr(self.elt, 'property'):
|
||||
for child in self.elt.property:
|
||||
self.populate_properties(child)
|
||||
|
||||
def get_object_name(self):
|
||||
"""Get family object's name
|
||||
"""
|
||||
|
Reference in New Issue
Block a user