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 .rougail import Rougail
from .annotator import modes from .annotator import modes

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,8 +1,7 @@
"""Annotate variable """Annotate variable
""" """
from ..i18n import _
from ..utils import normalize_family from ..utils import normalize_family
from ..error import DictConsistencyError from ..config import Config
CONVERT_OPTION = {'number': dict(opttype="IntOption", func=int), CONVERT_OPTION = {'number': dict(opttype="IntOption", func=int),
@ -51,10 +50,10 @@ class VariableAnnotator:
def __init__(self, def __init__(self,
objectspace, objectspace,
): ):
if not hasattr(objectspace.space, 'variables'):
return
self.objectspace = objectspace self.objectspace = objectspace
if hasattr(self.objectspace.space, 'variables'):
self.convert_variable() self.convert_variable()
self.convert_separators()
def _convert_variable(self, def _convert_variable(self,
namespace: str, namespace: str,
@ -120,6 +119,7 @@ class VariableAnnotator:
""" """
for families in self.objectspace.space.variables.values(): for families in self.objectspace.space.variables.values():
families.doc = families.name families.doc = families.name
families.path = families.name
for family in families.family.values(): for family in families.family.values():
family.doc = family.name family.doc = family.name
family.name = normalize_family(family.name) family.name = normalize_family(family.name)
@ -140,17 +140,3 @@ class VariableAnnotator:
variable, variable,
'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 source CDATA #IMPLIED >
<!ATTLIST override templating (True|False) "True"> <!ATTLIST override templating (True|False) "True">
<!ELEMENT variables (family*, separators*)> <!ELEMENT variables (family*)>
<!ELEMENT family (variable*)> <!ELEMENT family (variable*)>
<!ATTLIST family name CDATA #REQUIRED> <!ATTLIST family name CDATA #REQUIRED>
<!ATTLIST family description CDATA #IMPLIED> <!ATTLIST family description CDATA #IMPLIED>
@ -107,11 +107,6 @@
<!ATTLIST variable remove_fill (True|False) "False"> <!ATTLIST variable remove_fill (True|False) "False">
<!ATTLIST variable test CDATA #IMPLIED> <!ATTLIST variable test CDATA #IMPLIED>
<!ELEMENT separators (separator*)>
<!ELEMENT separator (#PCDATA)>
<!ATTLIST separator name CDATA #REQUIRED>
<!ELEMENT value (#PCDATA)> <!ELEMENT value (#PCDATA)>
<!ELEMENT constraints ((fill* | check* | condition* | group*)*)> <!ELEMENT constraints ((fill* | check* | condition* | group*)*)>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,3 +1,5 @@
"""Redefine Tiramisu object
"""
try: try:
from tiramisu3 import DynOptionDescription from tiramisu3 import DynOptionDescription
except ModuleNotFoundError: except ModuleNotFoundError:
@ -6,6 +8,9 @@ from .utils import normalize_family
class ConvertDynOptionDescription(DynOptionDescription): 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): def convert_suffix_to_path(self, suffix):
if not isinstance(suffix, str): if not isinstance(suffix, str):
suffix = str(suffix) suffix = str(suffix)

View File

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

View File

@ -1,8 +1,12 @@
""" """
utilitaires créole utilitaires créole
""" """
from typing import List
from unicodedata import normalize, combining 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: def normalize_family(family_name: str) -> str:
"""replace space, accent, uppercase, ... by valid character """replace space, accent, uppercase, ... by valid character
@ -11,3 +15,13 @@ def normalize_family(family_name: str) -> str:
nfkd_form = normalize('NFKD', family_name) nfkd_form = normalize('NFKD', family_name)
family_name = ''.join([c for c in nfkd_form if not combining(c)]) family_name = ''.join([c for c in nfkd_form if not combining(c)])
return family_name.lower() 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> <value>non</value>
</variable> </variable>
</family> </family>
<separators/>
</variables> </variables>
<constraints> <constraints>
<fill name="calc_val" target="mode_conteneur_actif"> <fill name="calc_val" target="mode_conteneur_actif">

View File

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

View File

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

View File

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

View File

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

View File

@ -9,7 +9,6 @@
<value>non</value> <value>non</value>
</variable> </variable>
</family> </family>
<separators/>
</variables> </variables>
<constraints> <constraints>
<fill name="calc_val" target="mode_conteneur_actif"> <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"> <family name="general">
<variable name="mode_conteneur_actif3" redefine="True"/> <variable name="mode_conteneur_actif3" redefine="True"/>
</family> </family>
<separators/>
</variables> </variables>
<constraints> <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> <value>non</value>
</variable> </variable>
</family> </family>
<separators/>
</variables> </variables>
<constraints> <constraints>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -2,12 +2,15 @@
<rougail> <rougail>
<variables> <variables>
<family name="général"> <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> <value>non</value>
</variable> </variable>
<variable name="activer_ejabberd" type="string" description="No change" hidden="True"> <variable name="activer_ejabberd" type="string" description="No change" hidden="True">
<value>non</value> <value>non</value>
</variable> </variable>
<variable name="module_instancie" type="string" description="No change" hidden="True">
<value>non</value>
</variable>
</family> </family>
</variables> </variables>
</rougail> </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> <value>non</value>
</variable> </variable>
</family> </family>
<separators/>
</variables> </variables>
<constraints> <constraints>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -6,7 +6,6 @@
<value>non</value> <value>non</value>
</variable> </variable>
</family> </family>
<separators/>
</variables> </variables>
<constraints> <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> <value>c</value>
</variable> </variable>
</family> </family>
<separators/>
</variables> </variables>
<constraints> <constraints>

View File

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

View File

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