Compare commits

...

6 Commits

Author SHA1 Message Date
Emmanuel Garette 686a218ed0 mutualise load_modules 2021-01-19 19:05:07 +01:00
Emmanuel Garette 0497698203 pylint 2021-01-19 18:06:33 +01:00
Emmanuel Garette 0d87be9d7b pylint + simplify path 2021-01-18 18:52:38 +01:00
Emmanuel Garette 0aba66b8b5 pylint path.py 2021-01-17 18:39:15 +01:00
Emmanuel Garette f0ba368f2a suppress separators 2021-01-17 18:12:33 +01:00
Emmanuel Garette fc2551a8d2 get_variable_obj => get_variable 2021-01-17 18:04:49 +01:00
93 changed files with 670 additions and 620 deletions

View File

@ -1,4 +1,5 @@
#from .loader import load
"""Rougail method
"""
from .rougail import Rougail
from .annotator import modes

View File

@ -1,10 +1,10 @@
"""Annotate check
"""
from importlib.machinery import SourceFileLoader
from typing import List, Any
from .variable import CONVERT_OPTION
from ..utils import load_modules
from ..i18n import _
from ..error import DictConsistencyError
@ -21,8 +21,7 @@ class CheckAnnotator:
not hasattr(objectspace.space.constraints, 'check'):
return
self.objectspace = objectspace
eosfunc = SourceFileLoader('eosfunc', eosfunc_file).load_module()
self.functions = dir(eosfunc)
self.functions = dir(load_modules(eosfunc_file))
self.functions.extend(INTERNAL_FUNCTIONS)
self.check_check()
self.check_valid_enum()
@ -41,7 +40,7 @@ class CheckAnnotator:
check_name = check.target
# let's replace the target by the an object
try:
check.target = self.objectspace.paths.get_variable_obj(check.target)
check.target = self.objectspace.paths.get_variable(check.target)
except DictConsistencyError as err:
if err.errno == 36:
xmlfiles = self.objectspace.display_xmlfiles(check.xmlfiles)
@ -63,7 +62,7 @@ class CheckAnnotator:
param_option_indexes.append(idx)
else:
# let's replace params by the path
param.text = self.objectspace.paths.get_variable_obj(param.text)
param.text = self.objectspace.paths.get_variable(param.text)
param_option_indexes.sort(reverse=True)
for idx in param_option_indexes:
check.param.pop(idx)

View File

@ -85,7 +85,7 @@ class Conditionnnotator:
msg = _('target name and source name must be different: '
f'{condition.source}')
raise DictConsistencyError(msg, 11)
target.name = self.objectspace.paths.get_variable_obj(target.name)
target.name = self.objectspace.paths.get_variable(target.name)
elif target.type == 'family':
target.name = self.objectspace.paths.get_family(target.name,
condition.namespace,
@ -203,7 +203,7 @@ class Conditionnnotator:
"""
for condition in self.objectspace.space.constraints.condition:
try:
condition.source = self.objectspace.paths.get_variable_obj(condition.source)
condition.source = self.objectspace.paths.get_variable(condition.source)
except DictConsistencyError as err:
if err.errno == 36:
xmlfiles = self.objectspace.display_xmlfiles(condition.xmlfiles)

View File

@ -169,7 +169,7 @@ class FamilyAnnotator:
for family in families.family.values():
if 'dynamic' not in vars(family):
continue
family.dynamic = self.objectspace.paths.get_variable_obj(family.dynamic)
family.dynamic = self.objectspace.paths.get_variable(family.dynamic)
if not family.dynamic.multi:
xmlfiles = self.objectspace.display_xmlfiles(family.xmlfiles)
msg = _(f'dynamic family "{family.name}" must be linked '

View File

@ -1,9 +1,7 @@
"""Fill annotator
"""
from importlib.machinery import SourceFileLoader
from ..utils import load_modules
from ..i18n import _
from ..error import DictConsistencyError
@ -18,8 +16,7 @@ class FillAnnotator:
if not hasattr(objectspace.space, 'constraints') or \
not hasattr(self.objectspace.space.constraints, 'fill'):
return
eosfunc = SourceFileLoader('eosfunc', eosfunc_file).load_module()
self.functions = dir(eosfunc)
self.functions = dir(load_modules(eosfunc_file))
self.convert_fill()
def convert_fill(self) -> None:
@ -52,7 +49,7 @@ class FillAnnotator:
raise DictConsistencyError(msg, 26)
# get the target variable
variable = self.objectspace.paths.get_variable_obj(fill.target)
variable = self.objectspace.paths.get_variable(fill.target)
# create an object value
value = self.objectspace.value(fill.xmlfiles)
@ -97,9 +94,13 @@ class FillAnnotator:
path, suffix = self.objectspace.paths.get_variable_path(param.text,
fill.namespace,
)
param.text = self.objectspace.paths.get_variable_obj(path)
param.text = self.objectspace.paths.get_variable(path)
if suffix:
param.suffix = suffix
family_path = self.objectspace.paths.get_variable_family_path(path)
param.family = self.objectspace.paths.get_family(family_path,
param.text.namespace,
)
except DictConsistencyError as err:
if err.errno != 42 or not param.optional:
raise err

View File

@ -1,9 +1,6 @@
"""Annotate group
"""
from typing import List
from ..i18n import _
from ..config import Config
from ..error import DictConsistencyError
@ -22,59 +19,45 @@ class GroupAnnotator:
def convert_groups(self): # pylint: disable=C0111
"""convert groups
"""
# store old leaders family name
cache_paths = {}
for group in self.objectspace.space.constraints.group:
leader_fullname = group.leader
leader = self.objectspace.paths.get_variable_obj(leader_fullname)
if leader_fullname in cache_paths:
leader_family_path = cache_paths[leader_fullname]
if group.leader in cache_paths:
leader_fam_path = cache_paths[group.leader]
else:
leader_family_path = self.objectspace.paths.get_variable_family_path(leader_fullname)
cache_paths[leader_fullname] = leader_family_path
if '.' not in leader_fullname:
leader_fullname = '.'.join([leader_family_path, leader_fullname])
leader_fam_path = self.objectspace.paths.get_variable_family_path(group.leader)
cache_paths[group.leader] = leader_fam_path
follower_names = list(group.follower.keys())
ori_leader_family = self.objectspace.paths.get_family(leader_family_path,
leader = self.objectspace.paths.get_variable(group.leader)
ori_leader_family = self.objectspace.paths.get_family(leader_fam_path,
leader.namespace,
)
has_a_leader = False
for variable in list(ori_leader_family.variable.values()):
if has_a_leader:
# it's a follower
self.manage_follower(leader_family_path,
variable,
leadership_name,
follower_names,
if isinstance(variable, self.objectspace.leadership) and \
variable.variable[0].name == leader.name:
# append follower to an existed leadership
leader_space = variable
has_a_leader = True
elif variable.name == leader.name:
# it's a leader
leader_space = self.manage_leader(variable,
group,
ori_leader_family,
)
if leader_is_hidden:
variable.frozen = True
variable.force_default_on_freeze = True
leader_space.variable.append(variable)
has_a_leader = True
elif has_a_leader:
# it's should be a follower
self.manage_follower(follower_names.pop(0),
leader_fam_path,
variable,
leader_space,
)
# this variable is not more in ori_leader_family
ori_leader_family.variable.pop(variable.name)
if follower_names == []:
# no more follower
break
elif variable.name == leader.name:
# it's a leader
if isinstance(variable, self.objectspace.leadership):
# append follower to an existed leadership
leader_space = variable
# if variable.hidden:
# leader_is_hidden = True
else:
leader_space = self.objectspace.leadership(variable.xmlfiles)
if hasattr(group, 'name'):
leadership_name = group.name
else:
leadership_name = leader.name
leader_is_hidden = self.manage_leader(leader_space,
leader_family_path,
leadership_name,
leader.name,
variable,
group,
)
has_a_leader = True
else:
xmlfiles = self.objectspace.display_xmlfiles(variable.xmlfiles)
joined = '", "'.join(follower_names)
@ -84,28 +67,27 @@ class GroupAnnotator:
del self.objectspace.space.constraints.group
def manage_leader(self,
leader_space: 'Leadership',
leader_family_name: str,
leadership_name: str,
leader_name: str,
variable: 'Variable',
group: 'Group',
) -> None:
ori_leader_family,
) -> 'Leadership':
"""manage leader's variable
"""
if variable.multi is not True:
xmlfiles = self.objectspace.display_xmlfiles(variable.xmlfiles)
msg = _(f'the variable "{variable.name}" in a group must be multi in {xmlfiles}')
raise DictConsistencyError(msg, 32)
if hasattr(group, 'name'):
leadership_name = group.name
else:
leadership_name = variable.name
leader_space = self.objectspace.leadership(variable.xmlfiles)
leader_space.variable = []
leader_space.name = leadership_name
leader_space.hidden = variable.hidden
if variable.hidden:
leader_is_hidden = True
variable.frozen = True
variable.force_default_on_freeze = True
else:
leader_is_hidden = False
variable.hidden = None
if hasattr(group, 'description'):
leader_space.doc = group.description
@ -113,38 +95,42 @@ class GroupAnnotator:
leader_space.doc = variable.description
else:
leader_space.doc = leadership_name
namespace = variable.namespace
leadership_path = leader_family_name + '.' + leadership_name
self.objectspace.paths.add_leadership(namespace,
leadership_path = ori_leader_family.path + '.' + leadership_name
self.objectspace.paths.add_leadership(variable.namespace,
leadership_path,
leader_space,
)
leader_family = self.objectspace.space.variables[namespace].family[leader_family_name.rsplit('.', 1)[-1]]
leader_family.variable[leader_name] = leader_space
leader_space.variable.append(variable)
self.objectspace.paths.set_leader(namespace,
leader_family_name,
leadership_name,
leader_name,
leader_family = self.objectspace.paths.get_family(ori_leader_family.path,
ori_leader_family.namespace,
)
return leader_is_hidden
leader_family.variable[variable.name] = leader_space
leader_space.variable.append(variable)
self.objectspace.paths.set_leader(variable.namespace,
ori_leader_family.path,
leadership_name,
variable.name,
)
return leader_space
def manage_follower(self,
follower_name: str,
leader_family_name: str,
variable: 'Variable',
leadership_name: str,
follower_names: List[str],
leader_space: 'Leadership',
) -> None:
"""manage follower
"""
follower_name = follower_names.pop(0)
if variable.name != follower_name:
xmlfiles = self.objectspace.display_xmlfiles(variable.xmlfiles)
msg = _('when parsing leadership, we espect to find the follower '
msg = _('when parsing leadership, we expect to find the follower '
f'"{follower_name}" but we found "{variable.name}" in {xmlfiles}')
raise DictConsistencyError(msg, 33)
self.objectspace.paths.set_leader(variable.namespace,
leader_family_name,
leadership_name,
leader_space.name,
variable.name,
)
if leader_space.hidden:
variable.frozen = True
variable.force_default_on_freeze = True
leader_space.variable.append(variable)

View File

@ -36,13 +36,15 @@ class PropertyAnnotator:
if hasattr(variable, 'mode') and variable.mode:
properties.append(variable.mode)
variable.mode = None
if 'force_store_value' in properties and 'force_default_on_freeze' in properties:
if 'force_store_value' in properties and \
'force_default_on_freeze' in 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 = frozenset(properties)
variable.properties = set(properties)
def convert_services(self) -> None:
"""convert services

View File

@ -10,7 +10,8 @@ from ..error import DictConsistencyError
# that shall not be present in the exported (flatened) XML
ERASED_ATTRIBUTES = ('redefine', 'exists', 'fallback', 'optional', 'remove_check', 'namespace',
'remove_condition', 'path', 'instance_mode', 'index', 'is_in_leadership',
'level', 'remove_fill', 'xmlfiles', 'type')
'level', 'remove_fill', 'xmlfiles', 'type', 'reflector_name',
'reflector_object',)
KEY_TYPE = {'variable': 'symlink',
@ -48,16 +49,18 @@ class ServiceAnnotator:
self.objectspace.space.services.hidden = True
self.objectspace.space.services.name = 'services'
self.objectspace.space.services.doc = 'services'
self.objectspace.space.services.path = 'services'
families = {}
for service_name in self.objectspace.space.services.service.keys():
service = self.objectspace.space.services.service[service_name]
new_service = self.objectspace.service(service.xmlfiles)
new_service.path = f'services.{service_name}'
for elttype, values in vars(service).items():
if not isinstance(values, (dict, list)) or elttype in ERASED_ATTRIBUTES:
setattr(new_service, elttype, values)
continue
eltname = elttype + 's'
path = '.'.join(['services', service_name, eltname])
path = '.'.join(['services', normalize_family(service_name), eltname])
family = self._gen_family(eltname,
path,
service.xmlfiles,
@ -145,7 +148,7 @@ class ServiceAnnotator:
c_name = name
if idx:
c_name += f'_{idx}'
subpath = '{}.{}'.format(path, c_name)
subpath = '{}.{}'.format(path, normalize_family(c_name))
try:
self.objectspace.paths.get_family(subpath, 'services')
except DictConsistencyError as err:
@ -180,7 +183,7 @@ class ServiceAnnotator:
variable.mode = None
variable.type = type_
if type_ == 'symlink':
variable.opt = self.objectspace.paths.get_variable_obj(value)
variable.opt = self.objectspace.paths.get_variable(value)
variable.multi = None
else:
variable.doc = key

View File

@ -1,8 +1,7 @@
"""Annotate variable
"""
from ..i18n import _
from ..utils import normalize_family
from ..error import DictConsistencyError
from ..config import Config
CONVERT_OPTION = {'number': dict(opttype="IntOption", func=int),
@ -51,10 +50,10 @@ class VariableAnnotator:
def __init__(self,
objectspace,
):
if not hasattr(objectspace.space, 'variables'):
return
self.objectspace = objectspace
if hasattr(self.objectspace.space, 'variables'):
self.convert_variable()
self.convert_separators()
def _convert_variable(self,
namespace: str,
@ -120,6 +119,7 @@ class VariableAnnotator:
"""
for families in self.objectspace.space.variables.values():
families.doc = families.name
families.path = families.name
for family in families.family.values():
family.doc = family.name
family.name = normalize_family(family.name)
@ -140,17 +140,3 @@ class VariableAnnotator:
variable,
'variable',
)
def convert_separators(self): # pylint: disable=C0111,R0201
for family in self.objectspace.space.variables.values():
if not hasattr(family, 'separators'):
continue
if hasattr(family.separators, 'separator'):
for separator in family.separators.separator:
option = self.objectspace.paths.get_variable_obj(separator.name)
if hasattr(option, 'separator'):
xmlfiles = self.objectspace.display_xmlfiles(separator.xmlfiles)
msg = _(f'{separator.name} already has a separator in {xmlfiles}')
raise DictConsistencyError(msg, 35)
option.separator = separator.text
del family.separators

View File

@ -79,7 +79,7 @@
<!ATTLIST override source CDATA #IMPLIED >
<!ATTLIST override templating (True|False) "True">
<!ELEMENT variables (family*, separators*)>
<!ELEMENT variables (family*)>
<!ELEMENT family (variable*)>
<!ATTLIST family name CDATA #REQUIRED>
<!ATTLIST family description CDATA #IMPLIED>
@ -107,11 +107,6 @@
<!ATTLIST variable remove_fill (True|False) "False">
<!ATTLIST variable test CDATA #IMPLIED>
<!ELEMENT separators (separator*)>
<!ELEMENT separator (#PCDATA)>
<!ATTLIST separator name CDATA #REQUIRED>
<!ELEMENT value (#PCDATA)>
<!ELEMENT constraints ((fill* | check* | condition* | group*)*)>

View File

@ -1,14 +1,18 @@
# -*- coding: utf-8 -*-
"""Standard error classes
"""
class ConfigError(Exception):
pass
"""Standard error for templating
"""
class FileNotFound(ConfigError):
pass
"""Template file is not found
"""
class TemplateError(ConfigError):
pass
"""Templating generate an error
"""
class TemplateDisabled(TemplateError):
@ -29,7 +33,3 @@ class DictConsistencyError(Exception):
def __init__(self, msg, errno):
super().__init__(msg)
self.errno = errno
class LoaderError(Exception):
pass

View File

@ -306,7 +306,7 @@ class RougailObjSpace:
) -> None:
"""if an object exists, return it
"""
if child.tag == 'family':
if child.tag in ['variable', 'family']:
name = normalize_family(name)
if isinstance(space, self.family): # pylint: disable=E1101
if namespace != Config['variable_namespace']:
@ -319,7 +319,8 @@ class RougailObjSpace:
msg = _(f'Variable was previously create in family "{old_family_name}", '
f'now it is in "{space.path}" in {xmlfiles}')
raise DictConsistencyError(msg, 47)
return self.paths.get_variable_obj(name)
return self.paths.get_variable(name)
# it's not a family
children = getattr(space, child.tag, {})
if name in children:
return children[name]
@ -437,7 +438,7 @@ class RougailObjSpace:
if isinstance(variableobj, self.variable): # pylint: disable=E1101
family_name = normalize_family(document.attrib['name'])
self.paths.add_variable(namespace,
variableobj.name,
normalize_family(variableobj.name),
namespace + '.' + family_name,
document.attrib.get('dynamic') is not None,
variableobj,
@ -462,7 +463,7 @@ class RougailObjSpace:
variableobj.namespace = namespace
if isinstance(variableobj, Redefinable):
name = variableobj.name
if child.tag == 'family':
if child.tag in ['family', 'variable']:
name = normalize_family(name)
getattr(space, child.tag)[name] = variableobj
elif isinstance(variableobj, UnRedefinable):

View File

@ -1,3 +1,5 @@
"""Manage path to find objects
"""
from .i18n import _
from .error import DictConsistencyError
from .config import Config
@ -22,12 +24,15 @@ class Path:
name: str,
variableobj: str,
) -> str: # pylint: disable=C0111
"""Add a new family
"""
if namespace == Config['variable_namespace']:
full_name = '.'.join([namespace, name])
self.full_paths_families[name] = full_name
else:
if '.' not in name:
raise DictConsistencyError(_(f'Variable "{name}" in namespace "{namespace}" must have dot'), 39)
if '.' not in name: # pragma: no cover
msg = _(f'Variable "{name}" in namespace "{namespace}" must have dot')
raise DictConsistencyError(msg, 39)
full_name = name
if full_name in self.families and \
self.families[full_name]['variableobj'] != variableobj: # pragma: no cover
@ -43,6 +48,8 @@ class Path:
path: str,
variableobj: str,
) -> str: # pylint: disable=C0111
"""add a new leadership
"""
self.families[path] = dict(name=path,
namespace=namespace,
variableobj=variableobj,
@ -53,14 +60,19 @@ class Path:
name: str,
current_namespace: str,
) -> 'Family': # pylint: disable=C0111
"""Get a family
"""
name = '.'.join([normalize_family(subname) for subname in name.split('.')])
if name not in self.families and name in self.full_paths_families:
name = self.full_paths_families[name]
if name not in self.families:
raise DictConsistencyError(_('unknown option {}').format(name), 42)
dico = self.families[name]
if current_namespace not in [Config['variable_namespace'], 'services'] and current_namespace != dico['namespace']:
raise DictConsistencyError(_(f'A family located in the "{dico["namespace"]}" namespace shall not be used in the "{current_namespace}" namespace'), 38)
if current_namespace not in [Config['variable_namespace'], 'services'] and \
current_namespace != dico['namespace']:
msg = _(f'A family located in the "{dico["namespace"]}" namespace '
f'shall not be used in the "{current_namespace}" namespace')
raise DictConsistencyError(msg, 38)
return dico['variableobj']
# Leadership
@ -70,6 +82,8 @@ class Path:
leadership_name: str,
name: str,
) -> None: # pylint: disable=C0111
"""set a variable a leadership member
"""
# need rebuild path and move object in new path
old_path = leader_family_name + '.' + name
leadership_path = leader_family_name + '.' + leadership_name
@ -82,9 +96,13 @@ class Path:
self.full_paths_variables[name] = new_path
def is_in_leadership(self, name):
"""Is the variable is in a leadership
"""
return self._get_variable(name)['leader'] is not None
def is_leader(self, path): # pylint: disable=C0111
"""Is the variable is a leader
"""
variable = self._get_variable(path)
if not variable['leader']:
return False
@ -99,6 +117,8 @@ class Path:
is_dynamic: bool,
variableobj,
) -> str: # pylint: disable=C0111
"""Add a new variable (with path)
"""
if '.' not in name:
full_path = '.'.join([family, name])
if namespace == Config['variable_namespace']:
@ -113,9 +133,11 @@ class Path:
variableobj=variableobj,
)
def get_variable_obj(self,
def get_variable(self,
name: str,
) -> 'Variable': # pylint: disable=C0111
"""Get variable object from a path
"""
variable, suffix = self._get_variable(name, with_suffix=True)
if suffix:
raise DictConsistencyError(_(f"{name} is a dynamic variable"), 36)
@ -124,30 +146,41 @@ class Path:
def get_variable_family_path(self,
name: str,
) -> str: # pylint: disable=C0111
"""Get the full path of a family
"""
return self._get_variable(name)['family']
def get_variable_path(self,
name: str,
current_namespace: str,
) -> str: # pylint: disable=C0111
"""get full path of a variable
"""
dico, suffix = self._get_variable(name,
with_suffix=True,
)
namespace = dico['variableobj'].namespace
if namespace not in [Config['variable_namespace'], 'services'] and current_namespace != namespace:
raise DictConsistencyError(_(f'A variable located in the "{namespace}" namespace shall not be used in the "{current_namespace}" namespace'), 41)
if namespace not in [Config['variable_namespace'], 'services'] and \
current_namespace != namespace:
msg = _(f'A variable located in the "{namespace}" namespace shall not be used '
f'in the "{current_namespace}" namespace')
raise DictConsistencyError(msg, 41)
return dico['variableobj'].path, suffix
def path_is_defined(self,
name: str,
path: str,
) -> str: # pylint: disable=C0111
if '.' not in name and name not in self.variables and name in self.full_paths_variables:
"""The path is a valid path
"""
if '.' not in path and path not in self.variables and path in self.full_paths_variables:
return True
return name in self.variables
return path in self.variables
def variable_is_dynamic(self,
name: str,
) -> bool:
"""This variable is in dynamic family
"""
return self._get_variable(name)['is_dynamic']
def _get_variable(self,

View File

@ -28,12 +28,15 @@ from .annotator import SpaceAnnotator
class Rougail:
"""Rougail object
"""
def __init__(self,
dtdfilename: str,
) -> None:
self.xmlreflector = XMLReflector()
self.xmlreflector.parse_dtd(dtdfilename)
self.rougailobjspace = RougailObjSpace(self.xmlreflector)
self.funcs_path = None
def create_or_populate_from_xml(self,
namespace: str,
@ -53,10 +56,14 @@ class Rougail:
def space_visitor(self,
eosfunc_file: str,
) -> None:
"""All XML are loader, now annotate content
"""
self.funcs_path = eosfunc_file
SpaceAnnotator(self.rougailobjspace, eosfunc_file)
def save(self) -> str:
"""Return tiramisu object declaration as a string
"""
tiramisu_objects = TiramisuReflector(self.rougailobjspace.space,
self.funcs_path,
)

View File

@ -4,7 +4,6 @@ Gestion du mini-langage de template
On travaille sur les fichiers cibles
"""
from importlib.machinery import SourceFileLoader
from shutil import copy
import logging
from typing import Dict, Any
@ -25,7 +24,7 @@ except ModuleNotFoundError: # pragma: no cover
from .config import Config
from .error import FileNotFound, TemplateError
from .i18n import _
from .utils import normalize_family
from .utils import normalize_family, load_modules
log = logging.getLogger(__name__)
@ -34,6 +33,8 @@ log.addHandler(logging.NullHandler())
@classmethod
def cl_compile(kls, *args, **kwargs):
"""Rewrite compile methode to force some settings
"""
kwargs['compilerSettings'] = {'directiveStartToken' : '%',
'cheetahVarStartToken' : '%%',
'EOLSlurpToken' : '%',
@ -49,23 +50,16 @@ ChtTemplate.compile = cl_compile
class CheetahTemplate(ChtTemplate):
"""classe pour personnaliser et faciliter la construction
du template Cheetah
"""Construct a cheetah templating object
"""
def __init__(self,
filename: str,
context,
eosfunc: Dict,
destfilename,
variable,
extra_context: Dict,
):
"""Initialize Creole CheetahTemplate
"""
extra_context = {'normalize_family': normalize_family,
'rougail_filename': destfilename
}
if variable:
extra_context['rougail_variable'] = variable
ChtTemplate.__init__(self,
file=filename,
searchList=[context, eosfunc, extra_context])
@ -75,12 +69,12 @@ class CheetahTemplate(ChtTemplate):
path=None,
normpath=normpath,
abspath=abspath
):
): # pylint: disable=W0621
# strange...
if path is None and isinstance(self, str):
path = self
if path:
if path: # pylint: disable=R1705
return normpath(abspath(path))
# original code return normpath(abspath(path.replace("\\", '/')))
elif hasattr(self, '_filePath') and self._filePath: # pragma: no cover
@ -90,6 +84,8 @@ class CheetahTemplate(ChtTemplate):
class CreoleLeaderIndex:
"""This object is create when access to a specified Index of the variable
"""
def __init__(self,
value,
follower,
@ -136,6 +132,9 @@ class CreoleLeaderIndex:
class CreoleLeader:
"""Implement access to leader and follower variable
For examples: %%leader, %%leader[0].follower1
"""
def __init__(self,
value,
) -> None:
@ -170,6 +169,8 @@ class CreoleLeader:
name: str,
path: str,
):
"""Add a new follower
"""
self._follower[name] = []
for index in range(len(self._value)):
try:
@ -180,6 +181,9 @@ class CreoleLeader:
class CreoleExtra:
"""Object that implement access to extra variable
For example %%extra1.family.variable
"""
def __init__(self,
suboption: Dict) -> None:
self.suboption = suboption
@ -209,60 +213,13 @@ class CreoleTemplateEngine:
self.distrib_dir = distrib_dir
eos = {}
if eosfunc_file is not None:
eosfunc = SourceFileLoader('eosfunc', eosfunc_file).load_module()
eosfunc = load_modules(eosfunc_file)
for func in dir(eosfunc):
if not func.startswith('_'):
eos[func] = getattr(eosfunc, func)
self.eosfunc = eos
self.rougail_variables_dict = {}
async def load_eole_variables_rougail(self,
optiondescription,
):
for option in await optiondescription.list('all'):
if await option.option.isoptiondescription():
if await option.option.isleadership():
for idx, suboption in enumerate(await option.list('all')):
if idx == 0:
leader = CreoleLeader(await suboption.value.get())
self.rougail_variables_dict[await suboption.option.name()] = leader
else:
await leader.add_follower(self.config,
await suboption.option.name(),
await suboption.option.path(),
)
else:
await self.load_eole_variables_rougail(option)
else:
self.rougail_variables_dict[await option.option.name()] = await option.value.get()
async def load_eole_variables(self,
optiondescription,
):
families = {}
for family in await optiondescription.list('all'):
variables = {}
for variable in await family.list('all'):
if await variable.option.isoptiondescription():
if await variable.option.isleadership():
for idx, suboption in enumerate(await variable.list('all')):
if idx == 0:
leader = CreoleLeader(await suboption.value.get())
leader_name = await suboption.option.name()
else:
await leader.add_follower(self.config,
await suboption.option.name(),
await suboption.option.path(),
)
variables[leader_name] = leader
else:
subfamilies = await self.load_eole_variables(variable)
variables[await variable.option.name()] = subfamilies
else:
variables[await variable.option.name()] = await variable.value.get()
families[await family.option.name()] = CreoleExtra(variables)
return CreoleExtra(families)
def patch_template(self,
filename: str,
tmp_dir: str,
@ -280,7 +237,9 @@ class CreoleTemplateEngine:
ret = call(patch_cmd + patch_no_debug + ['-i', rel_patch_file])
if ret: # pragma: no cover
patch_cmd_err = ' '.join(patch_cmd + ['-i', rel_patch_file])
log.error(_(f"Error applying patch: '{rel_patch_file}'\nTo reproduce and fix this error {patch_cmd_err}"))
msg = _(f"Error applying patch: '{rel_patch_file}'\n"
f"To reproduce and fix this error {patch_cmd_err}")
log.error(_(msg))
copy(join(self.distrib_dir, filename), tmp_dir)
def prepare_template(self,
@ -305,18 +264,24 @@ class CreoleTemplateEngine:
# full path of the destination file
log.info(_(f"Cheetah processing: '{destfilename}'"))
try:
extra_context = {'normalize_family': normalize_family,
'rougail_filename': true_destfilename
}
if variable:
extra_context['rougail_variable'] = variable
cheetah_template = CheetahTemplate(source,
self.rougail_variables_dict,
self.eosfunc,
true_destfilename,
variable,
extra_context,
)
data = str(cheetah_template)
except CheetahNotFound as err: # pragma: no cover
varname = err.args[0][13:-1]
raise TemplateError(_(f"Error: unknown variable used in template {source} to {destfilename} : {varname}"))
msg = f"Error: unknown variable used in template {source} to {destfilename}: {varname}"
raise TemplateError(_(msg))
except Exception as err: # pragma: no cover
raise TemplateError(_(f"Error while instantiating template {source} to {destfilename}: {err}"))
msg = _(f"Error while instantiating template {source} to {destfilename}: {err}")
raise TemplateError(msg)
with open(destfilename, 'w') as file_h:
file_h.write(data)
@ -366,10 +331,9 @@ class CreoleTemplateEngine:
for option in await self.config.option.list(type='all'):
namespace = await option.option.name()
if namespace == Config['variable_namespace']:
await self.load_eole_variables_rougail(option)
await self.load_variables_namespace(option)
else:
families = await self.load_eole_variables(option)
self.rougail_variables_dict[namespace] = families
self.rougail_variables_dict[namespace] = await self.load_variables_extra(option)
for template in listdir('.'):
self.prepare_template(template, tmp_dir, patch_dir)
for service_obj in await self.config.option('services').list('all'):
@ -389,6 +353,57 @@ class CreoleTemplateEngine:
log.debug(_("Instantiation of file '{filename}' disabled"))
chdir(ori_dir)
async def load_variables_namespace (self,
optiondescription,
):
"""load variables from the "variable namespace
"""
for option in await optiondescription.list('all'):
if await option.option.isoptiondescription():
if await option.option.isleadership():
for idx, suboption in enumerate(await option.list('all')):
if idx == 0:
leader = CreoleLeader(await suboption.value.get())
self.rougail_variables_dict[await suboption.option.name()] = leader
else:
await leader.add_follower(self.config,
await suboption.option.name(),
await suboption.option.path(),
)
else:
await self.load_variables_namespace(option)
else:
self.rougail_variables_dict[await option.option.name()] = await option.value.get()
async def load_variables_extra(self,
optiondescription,
) -> CreoleExtra:
"""Load all variables and set it in CreoleExtra objects
"""
families = {}
for family in await optiondescription.list('all'):
variables = {}
for variable in await family.list('all'):
if await variable.option.isoptiondescription():
if await variable.option.isleadership():
for idx, suboption in enumerate(await variable.list('all')):
if idx == 0:
leader = CreoleLeader(await suboption.value.get())
leader_name = await suboption.option.name()
else:
await leader.add_follower(self.config,
await suboption.option.name(),
await suboption.option.path(),
)
variables[leader_name] = leader
else:
subfamilies = await self.load_variables_extra(variable)
variables[await variable.option.name()] = subfamilies
else:
variables[await variable.option.name()] = await variable.value.get()
families[await family.option.name()] = CreoleExtra(variables)
return CreoleExtra(families)
async def generate(config: Config,
eosfunc_file: str,
@ -396,6 +411,8 @@ async def generate(config: Config,
tmp_dir: str,
dest_dir: str,
) -> None:
"""Generate all files
"""
engine = CreoleTemplateEngine(config,
eosfunc_file,
distrib_dir,

View File

@ -1,3 +1,5 @@
"""Redefine Tiramisu object
"""
try:
from tiramisu3 import DynOptionDescription
except ModuleNotFoundError:
@ -6,6 +8,9 @@ from .utils import normalize_family
class ConvertDynOptionDescription(DynOptionDescription):
"""Suffix could be an integer, we should convert it in str
Suffix could also contain invalid character, so we should "normalize" it
"""
def convert_suffix_to_path(self, suffix):
if not isinstance(suffix, str):
suffix = str(suffix)

View File

@ -2,27 +2,30 @@
flattened XML specific
"""
from .config import Config
from .i18n import _
from .error import LoaderError
from .annotator import ERASED_ATTRIBUTES, CONVERT_OPTION
#from .objspace import UnRedefinable, Redefinable, Atom
FUNC_TO_DICT = []
FORCE_INFORMATIONS = ['help', 'test', 'separator', 'manage']
FORCE_INFORMATIONS = ['help', 'test', 'manage']
ATTRIBUTES_ORDER = ('name', 'doc', 'default', 'multi')
class Root():
"""Root classes
"""
path = '.'
class TiramisuReflector:
"""Convert object to tiramisu representation
"""
def __init__(self,
xmlroot,
space,
funcs_path,
):
self.storage = ElementStorage()
self.storage.text = ["from importlib.machinery import SourceFileLoader",
self.index = 0
self.text = ["from importlib.machinery import SourceFileLoader",
f"func = SourceFileLoader('func', '{funcs_path}').load_module()",
"for key, value in dict(locals()).items():",
" if key != ['SourceFileLoader', 'func']:",
@ -33,62 +36,52 @@ class TiramisuReflector:
" from tiramisu import *",
"from rougail.tiramisu import ConvertDynOptionDescription",
]
self.make_tiramisu_objects(xmlroot)
# parse object
self.storage.get(Root()).get()
self.make_tiramisu_objects(space)
def make_tiramisu_objects(self,
xmlroot,
space,
):
family = self.get_root_family()
for xmlelt in self.reorder_family(xmlroot):
self.iter_family(xmlelt,
family,
None,
"""make tiramisu objects
"""
baseelt = BaseElt()
self.set_name(baseelt)
basefamily = Family(baseelt,
self.text,
)
def get_root_family(self):
family = Family(BaseElt(),
self.storage,
False,
'.',
for elt in self.reorder_family(space):
self.iter_family(basefamily,
elt,
)
return family
# parse object
baseelt.reflector_object.get()
def reorder_family(self, xmlroot):
# variable_namespace family has to be loaded before any other family
# because `extra` family could use `variable_namespace` variables.
if hasattr(xmlroot, 'variables'):
if Config['variable_namespace'] in xmlroot.variables:
yield xmlroot.variables[Config['variable_namespace']]
for xmlelt, value in xmlroot.variables.items():
if xmlelt != Config['variable_namespace']:
@staticmethod
def reorder_family(space):
"""variable_namespace family has to be loaded before any other family
because `extra` family could use `variable_namespace` variables.
"""
if hasattr(space, 'variables'):
if Config['variable_namespace'] in space.variables:
yield space.variables[Config['variable_namespace']]
for elt, value in space.variables.items():
if elt != Config['variable_namespace']:
yield value
if hasattr(xmlroot, 'services'):
yield xmlroot.services
if hasattr(space, 'services'):
yield space.services
def get_attributes(self, space): # pylint: disable=R0201
"""Get attributes
"""
for attr in dir(space):
if not attr.startswith('_') and attr not in ERASED_ATTRIBUTES:
yield attr
def get_children(self,
space,
):
for tag in self.get_attributes(space):
children = getattr(space, tag)
if children.__class__.__name__ == 'Family':
children = [children]
if isinstance(children, dict):
children = list(children.values())
if isinstance(children, list):
yield tag, children
def iter_family(self,
child,
family,
subpath,
child,
):
"""Iter each family
"""
tag = child.__class__.__name__
if tag == 'Variable':
function = self.populate_variable
@ -97,112 +90,104 @@ class TiramisuReflector:
return
else:
function = self.populate_family
#else:
# raise Exception('unknown tag {}'.format(child.tag))
function(family,
child,
subpath,
)
def populate_family(self,
parent_family,
elt,
subpath,
):
path = self.build_path(subpath,
elt,
)
tag = elt.__class__.__name__
"""Populate family
"""
self.set_name(elt)
family = Family(elt,
self.storage,
tag == 'Leadership',
path,
self.text,
)
parent_family.add(family)
for tag, children in self.get_children(elt):
for children in self.get_children(elt):
for child in children:
self.iter_family(child,
family,
path,
self.iter_family(family,
child,
)
def get_children(self,
space,
):
"""Get children
"""
for tag in self.get_attributes(space):
children = getattr(space, tag)
if children.__class__.__name__ == 'Family':
children = [children]
if isinstance(children, dict):
children = list(children.values())
if isinstance(children, list):
yield children
def populate_variable(self,
family,
elt,
subpath,
):
is_follower = False
is_leader = False
if family.is_leader:
if elt.name != family.elt.name:
is_follower = True
"""Populate variable
"""
if family.is_leadership:
is_leader = elt.name == family.elt.variable[0].name
is_follower = not is_leader
else:
is_leader = True
is_leader = False
is_follower = False
self.set_name(elt)
family.add(Variable(elt,
self.storage,
self.text,
is_follower,
is_leader,
self.build_path(subpath,
elt,
)
))
def build_path(self,
subpath,
def set_name(self,
elt,
):
if subpath is None:
return elt.name
return subpath + '.' + elt.name
"""Set name
"""
elt.reflector_name = f'option_{self.index}'
self.index += 1
def get_text(self):
return '\n'.join(self.storage.get(Root()).get_text())
"""Get text
"""
return '\n'.join(self.text)
class BaseElt:
def __init__(self) -> None:
self.name = 'baseoption'
self.doc = 'baseoption'
class ElementStorage:
def __init__(self,
):
self.paths = {}
self.text = []
self.index = 0
def add(self, path, elt):
self.paths[path] = (elt, self.index)
self.index += 1
def get(self, obj):
path = obj.path
return self.paths[path][0]
def get_name(self, path):
return f'option_{self.paths[path][1]}'
"""Base element
"""
name = 'baseoption'
doc = 'baseoption'
path = '.'
class Common:
"""Common function for variable and family
"""
def __init__(self,
storage,
is_leader,
path,
elt,
text,
):
self.elt = elt
self.option_name = None
self.path = path
self.attrib = {}
self.informations = {}
self.storage = storage
self.is_leader = is_leader
self.storage.add(self.path, self)
self.text = text
self.elt.reflector_object = self
def populate_properties(self, child):
"""Populate properties
"""
assert child.type == 'calculation'
action = f"ParamValue('{child.name}')"
option_name = self.storage.get(child.source).get()
kwargs = f"'condition': ParamOption({option_name}, todict=True), 'expected': ParamValue('{child.expected}')"
option_name = child.source.reflector_object.get()
kwargs = (f"'condition': ParamOption({option_name}, todict=True), "
f"'expected': ParamValue('{child.expected}')")
if child.inverse:
kwargs += ", 'reverse_condition': ParamValue(True)"
prop = 'Calculation(calc_value, Params(' + action + ', kwargs={' + kwargs + '}))'
@ -210,7 +195,17 @@ class Common:
self.attrib['properties'] += ', '
self.attrib['properties'] += prop
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'])) + "'"
def get_attrib(self):
"""Get attributes
"""
ret_list = []
for key, value in self.attrib.items():
if value is None:
@ -227,16 +222,16 @@ class Common:
return ', '.join(ret_list)
def populate_informations(self):
"""Populate Tiramisu's informations
"""
for key, value in self.informations.items():
if isinstance(value, str):
value = '"' + value.replace('"', '\"') + '"'
self.storage.text.append(f'{self.option_name}.impl_set_information("{key}", {value})')
def get_text(self,
):
return self.storage.text
self.text.append(f'{self.option_name}.impl_set_information("{key}", {value})')
def get_attributes(self, space): # pylint: disable=R0201
"""Get attributes
"""
attributes = dir(space)
for attr in ATTRIBUTES_ORDER:
if attr in attributes:
@ -245,12 +240,14 @@ class Common:
if attr not in ATTRIBUTES_ORDER:
if not attr.startswith('_') and attr not in ERASED_ATTRIBUTES:
value = getattr(space, attr)
if not isinstance(value, (list, dict)) and not value.__class__.__name__ == 'Family':
if not isinstance(value, (list, dict)) and \
not value.__class__.__name__ == 'Family':
yield attr
def get_children(self,
space,
):
@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):
@ -258,17 +255,16 @@ class Common:
class Variable(Common):
"""Manage variable
"""
def __init__(self,
elt,
storage,
text,
is_follower,
is_leader,
path,
):
super().__init__(storage,
is_leader,
path,
)
super().__init__(elt, text)
self.is_leader = is_leader
self.is_follower = is_follower
convert_option = CONVERT_OPTION[elt.type]
self.object_type = convert_option['opttype']
@ -276,22 +272,25 @@ class Variable(Common):
if self.object_type != 'SymLinkOption':
self.attrib['properties'] = []
self.attrib['validators'] = []
self.elt = elt
def get(self):
"""Get tiramisu's object
"""
if self.option_name is None:
self.populate_attrib()
if self.object_type == 'SymLinkOption':
self.attrib['opt'] = self.storage.get(self.attrib['opt']).get()
self.attrib['opt'] = self.attrib['opt'].reflector_object.get()
else:
self.parse_children()
attrib = self.get_attrib()
self.option_name = self.storage.get_name(self.path)
self.storage.text.append(f'{self.option_name} = {self.object_type}({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):
value = getattr(self.elt, key)
if key in FORCE_INFORMATIONS:
@ -306,48 +305,68 @@ class Variable(Common):
self.attrib[key] = value
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 = []
if 'properties' in self.attrib:
if self.attrib['properties']:
self.attrib['properties'] = "'" + "', '".join(sorted(list(self.attrib['properties']))) + "'"
else:
self.attrib['properties'] = ''
self.properties_to_string()
for tag, children in self.get_children(self.elt):
for child in children:
if tag == 'property':
self.populate_properties(child)
elif tag == 'value':
if child.type == 'calculation':
self.attrib['default'] = self.calculation_value(child, [])
else:
self.populate_value(child)
elif tag == 'check':
self.attrib['validators'].append(self.calculation_value(child, ['ParamSelfOption()']))
elif tag == 'choice':
if child.type == 'calculation':
value = self.storage.get(child.name).get()
choices = f"Calculation(func.calc_value, Params((ParamOption({value}))))"
else:
choices.append(child.name)
self.parse_child(tag,
child,
choices,
)
if choices:
if isinstance(choices, list):
self.attrib['values'] = str(tuple(choices))
else:
self.attrib['values'] = choices
if self.attrib['default'] == []:
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 self.attrib['validators'] == []:
if not self.attrib['validators']:
del self.attrib['validators']
else:
self.attrib['validators'] = '[' + ', '.join(self.attrib['validators']) + ']'
def calculation_value(self, child, args):
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,
)
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,
) -> str:
"""Generate calculated value
"""
kwargs = []
# has parameters
function = child.name
@ -358,7 +377,8 @@ class Variable(Common):
args.append(str(value))
else:
kwargs.append(f"'{param.name}': " + value)
ret = f"Calculation(func.{function}, Params((" + ', '.join(args) + "), kwargs=" + "{" + ', '.join(kwargs) + "})"
ret = f"Calculation(func.{function}, Params((" + ', '.join(args) + \
"), kwargs=" + "{" + ', '.join(kwargs) + "})"
if hasattr(child, 'warnings_only'):
ret += f', warnings_only={child.warnings_only}'
return ret + ')'
@ -367,6 +387,8 @@ class Variable(Common):
function: str,
param,
):
"""Populate variable parameters
"""
if param.type == 'string':
return f'ParamValue("{param.text}")'
if param.type == 'number':
@ -378,16 +400,22 @@ class Variable(Common):
}
if hasattr(param, 'suffix'):
value['suffix'] = param.suffix
value['family'] = param.family
return self.build_param(value)
if param.type == 'information':
return f'ParamInformation("{param.text}", None)'
if param.type == 'suffix':
return 'ParamSuffix()'
raise LoaderError(_('unknown param type {}').format(param.type)) # pragma: no cover
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)
@ -402,66 +430,76 @@ class Variable(Common):
else:
self.attrib['default'].append("'" + value + "'")
def build_param(self,
param,
):
option_name = self.storage.get(param['option']).get()
@staticmethod
def build_param(param) -> str:
"""build variable parameters
"""
option_name = param['option'].reflector_object.get()
ends = f"notraisepropertyerror={param['notraisepropertyerror']}, todict={param['todict']})"
if 'suffix' in param:
family = '.'.join(param['option'].path.split('.')[:-1])
family_option = self.storage.get_name(family)
return f"ParamDynOption({option_name}, '{param['suffix']}', {family_option}, notraisepropertyerror={param['notraisepropertyerror']}, todict={param['todict']})"
return f"ParamOption({option_name}, notraisepropertyerror={param['notraisepropertyerror']}, todict={param['todict']})"
family_name = param['family'].reflector_name
return f"ParamDynOption({option_name}, '{param['suffix']}', {family_name}, {ends}"
return f"ParamOption({option_name}, {ends}"
class Family(Common):
"""Manage family
"""
def __init__(self,
elt,
storage,
is_leader,
path,
text,
):
super().__init__(storage,
is_leader,
path,
)
super().__init__(elt, text)
self.is_leadership = self.elt.__class__.__name__ == 'Leadership'
self.children = []
self.elt = elt
def add(self, child):
"""Add a child
"""
self.children.append(child)
def get(self):
"""Get tiramisu's object
"""
if not self.option_name:
self.populate_attrib()
self.parse_children()
self.option_name = self.storage.get_name(self.path)
self.option_name = self.elt.reflector_name
object_name = self.get_object_name()
attrib = self.get_attrib() + ', children=[' + ', '.join([child.get() for child in self.children]) + ']'
self.storage.text.append(f'{self.option_name} = {object_name}({attrib})')
attrib = self.get_attrib() + \
', children=[' + ', '.join([child.get() for child in self.children]) + ']'
self.text.append(f'{self.option_name} = {object_name}({attrib})')
self.populate_informations()
return self.option_name
def populate_attrib(self):
"""parse a populate attributes
"""
for key in self.get_attributes(self.elt):
value = getattr(self.elt, key)
if key in FORCE_INFORMATIONS:
self.informations[key] = value
elif key == 'dynamic':
dynamic = self.storage.get(value).get()
self.attrib['suffixes'] = f"Calculation(func.calc_value, Params((ParamOption({dynamic}))))"
dynamic = value.reflector_object.get()
self.attrib['suffixes'] = \
f"Calculation(func.calc_value, Params((ParamOption({dynamic}))))"
else:
self.attrib[key] = value
def parse_children(self):
"""parse current children
"""
if 'properties' in self.attrib:
self.attrib['properties'] = "'" + "', '".join(sorted(list(self.attrib['properties']))) + "'"
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
"""
if 'suffixes' in self.attrib:
return 'ConvertDynOptionDescription'
if not self.is_leader:
return 'OptionDescription'
if self.is_leadership:
return 'Leadership'
return 'OptionDescription'

View File

@ -1,8 +1,12 @@
"""
utilitaires créole
"""
from typing import List
from unicodedata import normalize, combining
from importlib.machinery import SourceFileLoader
from importlib.util import spec_from_loader, module_from_spec
def normalize_family(family_name: str) -> str:
"""replace space, accent, uppercase, ... by valid character
@ -11,3 +15,13 @@ def normalize_family(family_name: str) -> str:
nfkd_form = normalize('NFKD', family_name)
family_name = ''.join([c for c in nfkd_form if not combining(c)])
return family_name.lower()
def load_modules(eosfunc_file) -> List[str]:
"""list all functions in eosfunc
"""
loader = SourceFileLoader('eosfunc', eosfunc_file)
spec = spec_from_loader(loader.name, loader)
eosfunc = module_from_spec(spec)
loader.exec_module(eosfunc)
return eosfunc

View File

@ -9,7 +9,6 @@
<value>non</value>
</variable>
</family>
<separators/>
</variables>
<constraints>
<fill name="calc_val" target="mode_conteneur_actif">

View File

@ -13,7 +13,6 @@
<value>non</value>
</variable>
</family>
<separators/>
</variables>
</rougail>
<!-- vim: ts=4 sw=4 expandtab

View File

@ -13,7 +13,6 @@
<value>non</value>
</variable>
</family>
<separators/>
</variables>
</rougail>
<!-- vim: ts=4 sw=4 expandtab

View File

@ -13,7 +13,6 @@
<value>non</value>
</variable>
</family>
<separators/>
</variables>
</rougail>
<!-- vim: ts=4 sw=4 expandtab

View File

@ -9,7 +9,6 @@
<value>0.527</value>
</variable>
</family>
<separators/>
</variables>
</rougail>
<!-- vim: ts=4 sw=4 expandtab

View File

@ -9,7 +9,6 @@
<value>non</value>
</variable>
</family>
<separators/>
</variables>
<constraints>
<fill name="calc_val" target="mode_conteneur_actif">

View File

@ -1,15 +0,0 @@
<?xml version='1.0' encoding='UTF-8'?>
<rougail>
<variables>
<family name="general">
<variable name="mode_conteneur_actif" type="string" description="No change" hidden="True">
<value>non</value>
</variable>
</family>
<separators>
<separator name="mode_conteneur_actif">Établissement</separator>
</separators>
</variables>
</rougail>
<!-- vim: ts=4 sw=4 expandtab
-->

View File

@ -1 +0,0 @@
{"rougail.general.mode_conteneur_actif": "non"}

View File

@ -1,15 +0,0 @@
from importlib.machinery import SourceFileLoader
func = SourceFileLoader('func', 'tests/dictionaries/../eosfunc/test.py').load_module()
for key, value in dict(locals()).items():
if key != ['SourceFileLoader', 'func']:
setattr(func, key, value)
try:
from tiramisu3 import *
except:
from tiramisu import *
from rougail.tiramisu import ConvertDynOptionDescription
option_3 = StrOption(properties=frozenset({'force_default_on_freeze', 'frozen', 'hidden', 'mandatory', 'normal'}), name='mode_conteneur_actif', doc='No change', multi=False, default='non')
option_3.impl_set_information("separator", "Établissement")
option_2 = OptionDescription(name='general', doc='general', properties=frozenset({'normal'}), children=[option_3])
option_1 = OptionDescription(name='rougail', doc='rougail', children=[option_2])
option_0 = OptionDescription(name='baseoption', doc='baseoption', children=[option_1])

View File

@ -1,15 +0,0 @@
<?xml version='1.0' encoding='UTF-8'?>
<rougail>
<variables>
<family name="general">
<variable name="mode_conteneur_actif" type="string" description="No change" hidden="True">
<value>non</value>
</variable>
</family>
<separators>
<separator name="mode_conteneur_actif">Établissement</separator>
</separators>
</variables>
</rougail>
<!-- vim: ts=4 sw=4 expandtab
-->

View File

@ -1 +0,0 @@
{"rougail.general.mode_conteneur_actif": "non"}

View File

@ -1,15 +0,0 @@
from importlib.machinery import SourceFileLoader
func = SourceFileLoader('func', 'tests/dictionaries/../eosfunc/test.py').load_module()
for key, value in dict(locals()).items():
if key != ['SourceFileLoader', 'func']:
setattr(func, key, value)
try:
from tiramisu3 import *
except:
from tiramisu import *
from rougail.tiramisu import ConvertDynOptionDescription
option_3 = StrOption(properties=frozenset({'force_default_on_freeze', 'frozen', 'hidden', 'mandatory', 'normal'}), name='mode_conteneur_actif', doc='No change', multi=False, default='non')
option_3.impl_set_information("separator", "Établissement")
option_2 = OptionDescription(name='general', doc='general', properties=frozenset({'normal'}), children=[option_3])
option_1 = OptionDescription(name='rougail', doc='rougail', children=[option_2])
option_0 = OptionDescription(name='baseoption', doc='baseoption', children=[option_1])

View File

@ -4,7 +4,6 @@
<family name="general">
<variable name="mode_conteneur_actif3" redefine="True"/>
</family>
<separators/>
</variables>
<constraints>

View File

@ -0,0 +1,28 @@
<?xml version='1.0' encoding='UTF-8'?>
<rougail>
<variables>
<family name="general">
<variable name="mode_conteneur_actif" type="string" description="No change">
<value>non</value>
</variable>
</family>
<family name="general1">
<variable name="leader" type="string" description="leader" multi="True" hidden="True"/>
<variable name="follower1" type="string" description="follower1"/>
<variable name="follower2" type="string" description="follower2"/>
</family>
</variables>
<constraints>
<fill name="calc_val" target="follower1">
<param name="valeur">valfill</param>
</fill>
<fill name="calc_val" target="follower2">
<param type="variable">follower1</param>
</fill>
<group leader="leader">
<follower>follower1</follower>
<follower>follower2</follower>
</group>
</constraints>
</rougail>

View File

@ -0,0 +1,14 @@
<?xml version='1.0' encoding='UTF-8'?>
<rougail>
<variables>
<family name="general1">
<variable name="follower3" type="string" description="follower3"/>
</family>
</variables>
<constraints>
<group leader="leader">
<follower>follower3</follower>
</group>
</constraints>
</rougail>

View File

@ -0,0 +1 @@
{"rougail.general.mode_conteneur_actif": "non", "rougail.general1.leader.leader": []}

View File

@ -0,0 +1,20 @@
from importlib.machinery import SourceFileLoader
func = SourceFileLoader('func', 'tests/dictionaries/../eosfunc/test.py').load_module()
for key, value in dict(locals()).items():
if key != ['SourceFileLoader', 'func']:
setattr(func, key, value)
try:
from tiramisu3 import *
except:
from tiramisu import *
from rougail.tiramisu import ConvertDynOptionDescription
option_3 = StrOption(properties=frozenset({'mandatory', 'normal'}), name='mode_conteneur_actif', doc='No change', multi=False, default='non')
option_2 = OptionDescription(name='general', doc='general', properties=frozenset({'normal'}), children=[option_3])
option_6 = StrOption(properties=frozenset({'force_default_on_freeze', 'frozen'}), name='leader', doc='leader', multi=True)
option_7 = StrOption(properties=frozenset({'force_default_on_freeze', 'frozen', 'normal'}), name='follower1', doc='follower1', multi=True, default=Calculation(func.calc_val, Params((), kwargs={'valeur': ParamValue("valfill")})))
option_8 = StrOption(properties=frozenset({'force_default_on_freeze', 'frozen', 'normal'}), name='follower2', doc='follower2', multi=True, default=Calculation(func.calc_val, Params((ParamOption(option_7, notraisepropertyerror=False, todict=False)), kwargs={})))
option_9 = StrOption(properties=frozenset({'force_default_on_freeze', 'frozen', 'normal'}), name='follower3', doc='follower3', multi=True)
option_5 = Leadership(name='leader', doc='leader', properties=frozenset({'hidden', 'normal'}), children=[option_6, option_7, option_8, option_9])
option_4 = OptionDescription(name='general1', doc='general1', properties=frozenset({'normal'}), children=[option_5])
option_1 = OptionDescription(name='rougail', doc='rougail', children=[option_2, option_4])
option_0 = OptionDescription(name='baseoption', doc='baseoption', children=[option_1])

View File

@ -0,0 +1,28 @@
<?xml version='1.0' encoding='UTF-8'?>
<rougail>
<variables>
<family name="general">
<variable name="mode_conteneur_actif" type="string" description="No change">
<value>non</value>
</variable>
</family>
<family name="general1">
<variable name="leader" type="string" description="leader" multi="True"/>
<variable name="follower1" type="string" description="follower1"/>
<variable name="follower2" type="string" description="follower2"/>
</family>
</variables>
<constraints>
<fill name="calc_val" target="follower1">
<param name="valeur">valfill</param>
</fill>
<fill name="calc_val" target="follower2">
<param type="variable">follower1</param>
</fill>
<group leader="leader" name="leadership">
<follower>follower1</follower>
<follower>follower2</follower>
</group>
</constraints>
</rougail>

View File

@ -0,0 +1,14 @@
<?xml version='1.0' encoding='UTF-8'?>
<rougail>
<variables>
<family name="general1">
<variable name="follower3" type="string" description="follower3"/>
</family>
</variables>
<constraints>
<group leader="leader">
<follower>follower3</follower>
</group>
</constraints>
</rougail>

View File

@ -0,0 +1 @@
{"rougail.general.mode_conteneur_actif": "non", "rougail.general1.leadership.leader": []}

View File

@ -0,0 +1,20 @@
from importlib.machinery import SourceFileLoader
func = SourceFileLoader('func', 'tests/dictionaries/../eosfunc/test.py').load_module()
for key, value in dict(locals()).items():
if key != ['SourceFileLoader', 'func']:
setattr(func, key, value)
try:
from tiramisu3 import *
except:
from tiramisu import *
from rougail.tiramisu import ConvertDynOptionDescription
option_3 = StrOption(properties=frozenset({'mandatory', 'normal'}), name='mode_conteneur_actif', doc='No change', multi=False, default='non')
option_2 = OptionDescription(name='general', doc='general', properties=frozenset({'normal'}), children=[option_3])
option_6 = StrOption(name='leader', doc='leader', multi=True)
option_7 = StrOption(properties=frozenset({'normal'}), name='follower1', doc='follower1', multi=True, default=Calculation(func.calc_val, Params((), kwargs={'valeur': ParamValue("valfill")})))
option_8 = StrOption(properties=frozenset({'normal'}), name='follower2', doc='follower2', multi=True, default=Calculation(func.calc_val, Params((ParamOption(option_7, notraisepropertyerror=False, todict=False)), kwargs={})))
option_9 = StrOption(properties=frozenset({'normal'}), name='follower3', doc='follower3', multi=True)
option_5 = Leadership(name='leadership', doc='leadership', properties=frozenset({'normal'}), children=[option_6, option_7, option_8, option_9])
option_4 = OptionDescription(name='general1', doc='general1', properties=frozenset({'normal'}), children=[option_5])
option_1 = OptionDescription(name='rougail', doc='rougail', children=[option_2, option_4])
option_0 = OptionDescription(name='baseoption', doc='baseoption', children=[option_1])

View File

@ -14,7 +14,6 @@
<value>non</value>
</variable>
</family>
<separators/>
</variables>
<constraints>

View File

@ -14,7 +14,6 @@
<value>non</value>
</variable>
</family>
<separators/>
</variables>
<constraints>

View File

@ -14,7 +14,6 @@
<value>non</value>
</variable>
</family>
<separators/>
</variables>
<constraints>

View File

@ -11,7 +11,6 @@
<value>c</value>
</variable>
</family>
<separators/>
</variables>
<constraints>

View File

@ -10,7 +10,6 @@
<family name="enumfam" mode="expert">
<variable name="enumvar" type="string" description="multi" mandatory="True"/>
</family>
<separators/>
</variables>
<constraints>

View File

@ -11,7 +11,6 @@
<value>b</value>
</variable>
</family>
<separators/>
</variables>
<constraints>

View File

@ -9,7 +9,6 @@
<family name="enumfam" mode="expert">
<variable name="enumvar" type="string" description="multi" help="bla bla bla"/>
</family>
<separators/>
</variables>
<constraints>

View File

@ -9,7 +9,6 @@
<family name="enumfam" mode="expert">
<variable name="enumvar" type="string" description="multi" help="bla bla bla"/>
</family>
<separators/>
</variables>
<constraints>

View File

@ -13,7 +13,6 @@
<value>non</value>
</variable>
</family>
<separators/>
</variables>
</rougail>
<!-- vim: ts=4 sw=4 expandtab

View File

@ -13,7 +13,6 @@
<value>non</value>
</variable>
</family>
<separators/>
</variables>
</rougail>
<!-- vim: ts=4 sw=4 expandtab

View File

@ -6,7 +6,6 @@
<value>non</value>
</variable>
</family>
<separators/>
</variables>
<constraints>

View File

@ -4,7 +4,6 @@
<family name="general">
<variable name="mode_conteneur_actif" type="string" description="No change" hidden="True"/>
</family>
<separators/>
</variables>
<constraints>

View File

@ -6,7 +6,6 @@
<value>oui</value>
</variable>
</family>
<separators/>
</variables>
</rougail>
<!-- vim: ts=4 sw=4 expandtab

View File

@ -6,7 +6,6 @@
<value>non</value>
</variable>
</family>
<separators/>
</variables>
</rougail>
<!-- vim: ts=4 sw=4 expandtab

View File

@ -12,6 +12,4 @@
</variable>
</family>
</variables>
<constraints>
</constraints>
</rougail>

View File

@ -14,6 +14,5 @@
<value>non</value>
</variable>
</family>
<separators/>
</variables>
</rougail>

View File

@ -16,7 +16,6 @@
<value>non</value>
</variable>
</family>
<separators/>
</variables>
</rougail>
<!-- vim: ts=4 sw=4 expandtab

View File

@ -2,12 +2,15 @@
<rougail>
<variables>
<family name="général">
<variable name="mode_conteneur_actif" type="string" description="No change" hidden="True">
<variable name="mode_conteneur_actif" type="string" description="No change" auto_freeze="True">
<value>non</value>
</variable>
<variable name="activer_ejabberd" type="string" description="No change" hidden="True">
<value>non</value>
</variable>
<variable name="module_instancie" type="string" description="No change" hidden="True">
<value>non</value>
</variable>
</family>
</variables>
</rougail>

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<rougail>
<variables>
<family name='ejabberd'>
<variable name="description" type="string">
<value>Exportation de la base de ejabberd</value>
</variable>
<variable name="day" type="schedule"></variable>
<variable name="mode" type="schedulemod">
<value>pre</value>
</variable>
</family>
</variables>
</rougail>

View File

@ -0,0 +1 @@
{"rougail.general.mode_conteneur_actif": "non", "rougail.general.activer_ejabberd": "non", "rougail.general.module_instancie": "non", "extra.ejabberd.description": "Exportation de la base de ejabberd", "extra.ejabberd.day": "none", "extra.ejabberd.mode": "pre"}

View File

@ -0,0 +1,21 @@
from importlib.machinery import SourceFileLoader
func = SourceFileLoader('func', 'tests/dictionaries/../eosfunc/test.py').load_module()
for key, value in dict(locals()).items():
if key != ['SourceFileLoader', 'func']:
setattr(func, key, value)
try:
from tiramisu3 import *
except:
from tiramisu import *
from rougail.tiramisu import ConvertDynOptionDescription
option_5 = StrOption(properties=frozenset({'force_default_on_freeze', 'frozen', 'hidden', 'mandatory', 'normal'}), name='module_instancie', doc='No change', multi=False, default='non')
option_3 = StrOption(properties=frozenset({'auto_freeze', 'basic', 'force_store_value', 'mandatory', Calculation(calc_value, Params(ParamValue('auto_frozen'), kwargs={'condition': ParamOption(option_5, todict=True), 'expected': ParamValue('oui'), 'reverse_condition': ParamValue(True)}))}), name='mode_conteneur_actif', doc='No change', multi=False, default='non')
option_4 = StrOption(properties=frozenset({'force_default_on_freeze', 'frozen', 'hidden', 'mandatory', 'normal'}), name='activer_ejabberd', doc='No change', multi=False, default='non')
option_2 = OptionDescription(name='general', doc='général', properties=frozenset({'basic'}), children=[option_3, option_4, option_5])
option_1 = OptionDescription(name='rougail', doc='rougail', children=[option_2])
option_8 = StrOption(properties=frozenset({'mandatory', 'normal'}), name='description', doc='description', multi=False, default='Exportation de la base de ejabberd')
option_9 = ChoiceOption(properties=frozenset({'mandatory', 'normal'}), name='day', doc='day', multi=False, default='none', values=('none', 'daily', 'weekly', 'monthly'))
option_10 = ChoiceOption(properties=frozenset({'mandatory', 'normal'}), name='mode', doc='mode', multi=False, default='pre', values=('pre', 'post'))
option_7 = OptionDescription(name='ejabberd', doc='ejabberd', properties=frozenset({'normal'}), children=[option_8, option_9, option_10])
option_6 = OptionDescription(name='extra', doc='extra', children=[option_7])
option_0 = OptionDescription(name='baseoption', doc='baseoption', children=[option_1, option_6])

View File

@ -1,26 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<rougail>
<variables>
<family name='ejabberd'>
<variable name="description" type="string">
<value>Exportation de la base de ejabberd</value>
</variable>
<variable name="day" type="schedule"></variable>
<variable name="mode" type="schedulemod">
<value>pre</value>
</variable>
</family>
<separators>
<separator name="extra.ejabberd.day">Séparateur</separator>
</separators>
</variables>
<constraints>
<fill name='calc_multi_condition' target='extra.ejabberd.day'>
<param>non</param>
<param type='variable' name='condition_1' notraisepropertyerror='True'>activer_ejabberd</param>
<param name='match'>none</param>
<param name='mismatch'>daily</param>
</fill>
</constraints>
</rougail>

View File

@ -1 +0,0 @@
{"rougail.general.mode_conteneur_actif": "non", "rougail.general.activer_ejabberd": "non", "extra.ejabberd.description": "Exportation de la base de ejabberd", "extra.ejabberd.day": null, "extra.ejabberd.mode": "pre"}

View File

@ -1,21 +0,0 @@
from importlib.machinery import SourceFileLoader
func = SourceFileLoader('func', 'tests/dictionaries/../eosfunc/test.py').load_module()
for key, value in dict(locals()).items():
if key != ['SourceFileLoader', 'func']:
setattr(func, key, value)
try:
from tiramisu3 import *
except:
from tiramisu import *
from rougail.tiramisu import ConvertDynOptionDescription
option_3 = StrOption(properties=frozenset({'force_default_on_freeze', 'frozen', 'hidden', 'mandatory', 'normal'}), name='mode_conteneur_actif', doc='No change', multi=False, default='non')
option_4 = StrOption(properties=frozenset({'force_default_on_freeze', 'frozen', 'hidden', 'mandatory', 'normal'}), name='activer_ejabberd', doc='No change', multi=False, default='non')
option_2 = OptionDescription(name='general', doc='général', properties=frozenset({'normal'}), children=[option_3, option_4])
option_1 = OptionDescription(name='rougail', doc='rougail', children=[option_2])
option_7 = StrOption(properties=frozenset({'mandatory', 'normal'}), name='description', doc='description', multi=False, default='Exportation de la base de ejabberd')
option_8 = ChoiceOption(properties=frozenset({'mandatory', 'normal'}), name='day', doc='day', multi=False, default=Calculation(func.calc_multi_condition, Params((ParamValue("non")), kwargs={'condition_1': ParamOption(option_4, notraisepropertyerror=True, todict=False), 'match': ParamValue("none"), 'mismatch': ParamValue("daily")})), values=('none', 'daily', 'weekly', 'monthly'))
option_8.impl_set_information("separator", "Séparateur")
option_9 = ChoiceOption(properties=frozenset({'mandatory', 'normal'}), name='mode', doc='mode', multi=False, default='pre', values=('pre', 'post'))
option_6 = OptionDescription(name='ejabberd', doc='ejabberd', properties=frozenset({'normal'}), children=[option_7, option_8, option_9])
option_5 = OptionDescription(name='extra', doc='extra', children=[option_6])
option_0 = OptionDescription(name='baseoption', doc='baseoption', children=[option_1, option_5])

View File

@ -11,7 +11,6 @@
<value>non</value>
</variable>
</family>
<separators/>
</variables>
<constraints>

View File

@ -140,7 +140,6 @@
<value>non</value>
</variable>
</family>
<separators/>
</family>
<family doc="" name="extra">
<family hidden="False" mode="basic" doc="test" name="test">

View File

@ -15,6 +15,5 @@
<value>/etc/mailname2</value>
</variable>
</family>
<separators/>
</variables>
</rougail>

View File

@ -19,6 +19,5 @@
<value>mailname2</value>
</variable>
</family>
<separators/>
</variables>
</rougail>

View File

@ -17,6 +17,5 @@
<value>mailname</value>
</variable>
</family>
<separators/>
</variables>
</rougail>

View File

@ -6,7 +6,6 @@
<value>non</value>
</variable>
</family>
<separators/>
</variables>
<constraints>

View File

@ -6,7 +6,6 @@
<value>non</value>
</variable>
</family>
<separators/>
</variables>
<constraints>

View File

@ -14,6 +14,5 @@
<value>/etc/mailname</value>
</variable>
</family>
<separators/>
</variables>
</rougail>

View File

@ -6,7 +6,6 @@
<value>non</value>
</variable>
</family>
<separators/>
</variables>
</rougail>
<!-- vim: ts=4 sw=4 expandtab

View File

@ -6,7 +6,6 @@
<value>non</value>
</variable>
</family>
<separators/>
</variables>
</rougail>
<!-- vim: ts=4 sw=4 expandtab

View File

@ -6,7 +6,6 @@
<value>non</value>
</variable>
</family>
<separators/>
</variables>
<constraints>

View File

@ -1,16 +0,0 @@
<?xml version='1.0' encoding='UTF-8'?>
<rougail>
<variables>
<family name="general">
<variable name="mode_conteneur_actif" type="string" description="No change" hidden="True">
<value>non</value>
</variable>
</family>
<separators>
<separator name="mode_conteneur_actif">Établissement</separator>
<separator name="mode_conteneur_actif">Établissement</separator>
</separators>
</variables>
</rougail>
<!-- vim: ts=4 sw=4 expandtab
-->

View File

@ -1,15 +0,0 @@
<?xml version='1.0' encoding='UTF-8'?>
<rougail>
<variables>
<family name="general">
<variable name="mode_conteneur_actif" type="string" description="No change" hidden="True">
<value>non</value>
</variable>
</family>
<separators>
<separator name="mode_conteneur_actif">Établissement</separator>
</separators>
</variables>
</rougail>
<!-- vim: ts=4 sw=4 expandtab
-->

View File

@ -1,8 +0,0 @@
<?xml version='1.0' encoding='UTF-8'?>
<rougail>
<variables>
<separators>
<separator name="mode_conteneur_actif">Établissement</separator>
</separators>
</variables>
</rougail>

View File

@ -1,16 +0,0 @@
<?xml version='1.0' encoding='UTF-8'?>
<rougail>
<variables>
<family name="general">
<variable name="mode_conteneur_actif" type="string" description="No change" hidden="True">
<value>non</value>
</variable>
</family>
<separators>
<separator name="mode_conteneur_actif">Établissement</separator>
<separator name="nonexist_variable">separator</separator>
</separators>
</variables>
</rougail>
<!-- vim: ts=4 sw=4 expandtab
-->

View File

@ -11,7 +11,6 @@
<value>c</value>
</variable>
</family>
<separators/>
</variables>
<constraints>

View File

@ -9,7 +9,6 @@
<family name="enumfam" mode="expert">
<variable name="enumvar" type="number" description="enumvar"/>
</family>
<separators/>
</variables>
<constraints>

View File

@ -11,7 +11,6 @@
<value>non</value>
</variable>
</family>
<separators/>
</variables>
<constraints>