Compare commits

...

2 Commits

Author SHA1 Message Date
Emmanuel Garette f4471c4875 can add extra annotators 2021-04-12 15:04:38 +02:00
Emmanuel Garette b7cedd85fb support leadership name in extra 2021-04-12 15:04:15 +02:00
28 changed files with 404 additions and 89 deletions

View File

@ -74,15 +74,15 @@ Voici un exemple de définition d'une variable meneuse et de deux variables mene
</variables> </variables>
<constraints> <constraints>
<group leader="example.family.leader"> <group leader="example.family.leader">
<follower>example.family.follower1</follower> <follower>follower1</follower>
<follower>example.family.follower2</follower> <follower>follower2</follower>
</group> </group>
</constraints> </constraints>
``` ```
Le chemin de la variable meneuse est traditionnel, par contre le chemin des variables suiveuses n'est pas le chemin définitif de la variable. Le chemin de la variable meneuse est traditionnel, par contre le chemin des variables suiveuses est le chemin relatif de la variable.
Le chemin d'une variable suiveuse est normalement "example.family.leader.follower1" mais la variable n'est pas encore une variable suiveuse à ce moment là du traitement. C'est pour cela qu'il ne faut, uniquement dans les groupes, mettre le nom de la variable meneuse dans le chemin. Le chemin d'une variable suiveuse est normalement "example.family.leader.follower1" mais la variable n'est pas encore une variable suiveuse à ce moment là du traitement. C'est pour cela qu'il ne faut, uniquement dans les groupes, mettre le nom de la variable suiveuse.
## Ajout d'une nouvelle variable suiveuse ## Ajout d'une nouvelle variable suiveuse

View File

@ -24,34 +24,44 @@ You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
""" """
from .group import GroupAnnotator from .variable import CONVERT_OPTION
from .service import ServiceAnnotator import importlib.resources
from .variable import VariableAnnotator, CONVERT_OPTION from ..utils import load_modules
from .check import CheckAnnotator
from .value import ValueAnnotator
from .condition import ConditionAnnotator ANNOTATORS = None
from .fill import FillAnnotator
from .family import FamilyAnnotator
from .property import PropertyAnnotator def get_level(module):
return module.level
def get_annotators(annotators, module_name):
annotators[module_name] = []
for pathobj in importlib.resources.files(module_name).iterdir():
path = str(pathobj)
if not path.endswith('__') and not path.endswith('__.py'):
module = load_modules(path)
if 'Annotator' in dir(module):
annotators[module_name].append(module.Annotator)
class SpaceAnnotator: # pylint: disable=R0903 class SpaceAnnotator: # pylint: disable=R0903
"""Transformations applied on a object instance """Transformations applied on a object instance
""" """
def __init__(self, objectspace, eosfunc_file): def __init__(self, objectspace, eosfunc_file):
self.objectspace = objectspace global ANNOTATORS
GroupAnnotator(objectspace) if ANNOTATORS is None:
ServiceAnnotator(objectspace) ANNOTATORS = {}
VariableAnnotator(objectspace) get_annotators(ANNOTATORS, 'rougail.annotator')
CheckAnnotator(objectspace, for extra_annotator in objectspace.rougailconfig['extra_annotators']:
eosfunc_file, get_annotators(ANNOTATORS, extra_annotator)
) annotators = ANNOTATORS['rougail.annotator'].copy()
ConditionAnnotator(objectspace) for extra_annotator in objectspace.rougailconfig['extra_annotators']:
FillAnnotator(objectspace, annotators.extend(ANNOTATORS[extra_annotator])
eosfunc_file, annotators = sorted(annotators, key=get_level)
) for annotator in annotators:
ValueAnnotator(objectspace) annotator(objectspace, eosfunc_file)
FamilyAnnotator(objectspace)
PropertyAnnotator(objectspace)
__all__ = ('SpaceAnnotator', 'CONVERT_OPTION') __all__ = ('SpaceAnnotator', 'CONVERT_OPTION')

View File

@ -26,21 +26,23 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
""" """
from typing import List, Any from typing import List, Any
from .target import TargetAnnotator from rougail.annotator.target import TargetAnnotator
from .param import ParamAnnotator from rougail.annotator.param import ParamAnnotator
from ..utils import load_modules from rougail.utils import load_modules
from ..i18n import _ from rougail.i18n import _
from ..error import DictConsistencyError, display_xmlfiles from rougail.error import DictConsistencyError, display_xmlfiles
INTERNAL_FUNCTIONS = ['valid_enum', 'valid_in_network', 'valid_differ', 'valid_entier'] INTERNAL_FUNCTIONS = ['valid_enum', 'valid_in_network', 'valid_differ', 'valid_entier']
class CheckAnnotator(TargetAnnotator, ParamAnnotator): class Annotator(TargetAnnotator, ParamAnnotator):
"""Annotate check """Annotate check
""" """
level = 40
def __init__(self, def __init__(self,
objectspace, objectspace,
eosfunc_file, eosfunc_file,
*args,
): ):
if not hasattr(objectspace.space, 'constraints') or \ if not hasattr(objectspace.space, 'constraints') or \
not hasattr(objectspace.space.constraints, 'check'): not hasattr(objectspace.space.constraints, 'check'):

View File

@ -27,19 +27,21 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
from typing import List from typing import List
from ..i18n import _ from rougail.i18n import _
from ..error import DictConsistencyError from rougail.error import DictConsistencyError
from .target import TargetAnnotator from rougail.annotator.target import TargetAnnotator
from .param import ParamAnnotator from rougail.annotator.param import ParamAnnotator
from .variable import Walk from rougail.annotator.variable import Walk
class ConditionAnnotator(TargetAnnotator, ParamAnnotator, Walk): class Annotator(TargetAnnotator, ParamAnnotator, Walk):
"""Annotate condition """Annotate condition
""" """
level = 50
def __init__(self, def __init__(self,
objectspace, objectspace,
*args,
): ):
self.objectspace = objectspace self.objectspace = objectspace
self.force_service_value = {} self.force_service_value = {}

View File

@ -24,9 +24,9 @@ You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
""" """
from ..i18n import _ from rougail.i18n import _
from ..error import DictConsistencyError from rougail.error import DictConsistencyError
from .variable import Walk from rougail.annotator.variable import Walk
class Mode: # pylint: disable=R0903 class Mode: # pylint: disable=R0903
@ -43,11 +43,13 @@ class Mode: # pylint: disable=R0903
return other.level < self.level return other.level < self.level
class FamilyAnnotator(Walk): class Annotator(Walk):
"""Annotate family """Annotate family
""" """
level = 80
def __init__(self, def __init__(self,
objectspace, objectspace,
*args,
): ):
self.objectspace = objectspace self.objectspace = objectspace
if not hasattr(self.objectspace.space, 'variables'): if not hasattr(self.objectspace.space, 'variables'):
@ -74,6 +76,7 @@ class FamilyAnnotator(Walk):
def remove_empty_families(self) -> None: def remove_empty_families(self) -> None:
"""Remove all families without any variable """Remove all families without any variable
""" """
#FIXME pas sous family
for families in self.objectspace.space.variables.values(): for families in self.objectspace.space.variables.values():
removed_families = [] removed_families = []
for family_name, family in families.variable.items(): for family_name, family in families.variable.items():

View File

@ -24,28 +24,30 @@ You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
""" """
from ..utils import load_modules from rougail.utils import load_modules
from ..i18n import _ from rougail.i18n import _
from ..error import DictConsistencyError from rougail.error import DictConsistencyError
from .target import TargetAnnotator from rougail.annotator.target import TargetAnnotator
from .param import ParamAnnotator from rougail.annotator.param import ParamAnnotator
CALC_MULTI = ('calc_value', 'calc_list', 'get_range', 'calc_val_first_value', 'unbound_filename') CALC_MULTI = ('calc_value', 'calc_list', 'get_range', 'calc_val_first_value', 'unbound_filename')
class FillAnnotator(TargetAnnotator, ParamAnnotator): class Annotator(TargetAnnotator, ParamAnnotator):
"""Fill annotator """Fill annotator
""" """
level = 60
def __init__(self, def __init__(self,
objectspace, objectspace,
eosfunc_file, eosfunc_file,
*args,
): ):
self.objectspace = objectspace
if not hasattr(objectspace.space, 'constraints') or \ if not hasattr(objectspace.space, 'constraints') or \
not hasattr(self.objectspace.space.constraints, 'fill'): not hasattr(objectspace.space.constraints, 'fill'):
return return
self.objectspace = objectspace
self.functions = dir(load_modules(eosfunc_file)) self.functions = dir(load_modules(eosfunc_file))
self.functions.extend(self.objectspace.rougailconfig['internal_functions']) self.functions.extend(self.objectspace.rougailconfig['internal_functions'])
self.target_is_uniq = True self.target_is_uniq = True
@ -68,12 +70,11 @@ class FillAnnotator(TargetAnnotator, ParamAnnotator):
"""valid and manage <fill> """valid and manage <fill>
""" """
for fill in self.objectspace.space.constraints.fill: for fill in self.objectspace.space.constraints.fill:
for target in fill.target:
# test if the function exists # test if the function exists
if fill.name not in self.functions: if fill.name not in self.functions:
msg = _(f'cannot find fill function "{fill.name}"') msg = _(f'cannot find fill function "{fill.name}"')
raise DictConsistencyError(msg, 25, fill.xmlfiles) raise DictConsistencyError(msg, 25, fill.xmlfiles)
for target in fill.target:
# create an object value # create an object value
value = self.objectspace.value(fill.xmlfiles) value = self.objectspace.value(fill.xmlfiles)
value.type = 'calculation' value.type = 'calculation'
@ -87,7 +88,6 @@ class FillAnnotator(TargetAnnotator, ParamAnnotator):
target.name.default = value target.name.default = value
else: else:
target.name.value = [value] target.name.value = [value]
# manage params # manage params
if hasattr(fill, 'param') and fill.param: if hasattr(fill, 'param') and fill.param:
value.param = fill.param value.param = fill.param

View File

@ -24,16 +24,18 @@ You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
""" """
from ..i18n import _ from rougail.i18n import _
from ..error import DictConsistencyError from rougail.error import DictConsistencyError
from ..utils import normalize_family from rougail.utils import normalize_family
class GroupAnnotator: class Annotator:
"""Annotate group """Annotate group
""" """
level = 10
def __init__(self, def __init__(self,
objectspace, objectspace,
*args,
): ):
self.objectspace = objectspace self.objectspace = objectspace
if not hasattr(self.objectspace.space, 'constraints') or \ if not hasattr(self.objectspace.space, 'constraints') or \

View File

@ -29,10 +29,10 @@ try:
except ModuleNotFoundError: except ModuleNotFoundError:
import tiramisu import tiramisu
from .variable import CONVERT_OPTION from rougail.annotator.variable import CONVERT_OPTION
from ..i18n import _ from rougail.i18n import _
from ..error import DictConsistencyError from rougail.error import DictConsistencyError
class ParamAnnotator: class ParamAnnotator:

View File

@ -24,19 +24,23 @@ You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
""" """
from ..i18n import _ from rougail.i18n import _
from ..error import DictConsistencyError from rougail.error import DictConsistencyError
from .variable import Walk from rougail.annotator.variable import Walk
PROPERTIES = ('hidden', 'frozen', 'force_default_on_freeze', PROPERTIES = ('hidden', 'frozen', 'force_default_on_freeze',
'force_store_value', 'disabled', 'mandatory') 'force_store_value', 'disabled', 'mandatory')
class PropertyAnnotator(Walk): class Annotator(Walk):
"""Annotate properties """Annotate properties
""" """
def __init__(self, objectspace): level = 90
def __init__(self,
objectspace,
*args
) -> None:
self.objectspace = objectspace self.objectspace = objectspace
if hasattr(self.objectspace.space, 'services'): if hasattr(self.objectspace.space, 'services'):
self.convert_services() self.convert_services()

View File

@ -27,9 +27,9 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
from os.path import basename from os.path import basename
from typing import Tuple from typing import Tuple
from ..i18n import _ from rougail.i18n import _
from ..utils import normalize_family from rougail.utils import normalize_family
from ..error import DictConsistencyError from rougail.error import DictConsistencyError
# a object's attribute has some annotations # a object's attribute has some annotations
# that shall not be present in the exported (flatened) XML # that shall not be present in the exported (flatened) XML
ERASED_ATTRIBUTES = ('redefine', 'exists', 'optional', 'remove_check', 'namespace', ERASED_ATTRIBUTES = ('redefine', 'exists', 'optional', 'remove_check', 'namespace',
@ -39,7 +39,7 @@ ERASED_ATTRIBUTES = ('redefine', 'exists', 'optional', 'remove_check', 'namespac
ALLOW_ATTRIBUT_NOT_MANAGE = ['file'] ALLOW_ATTRIBUT_NOT_MANAGE = ['file']
class ServiceAnnotator: class Annotator:
"""Manage service's object """Manage service's object
for example:: for example::
<services> <services>
@ -49,7 +49,11 @@ class ServiceAnnotator:
</service> </service>
</services> </services>
""" """
def __init__(self, objectspace): level = 20
def __init__(self,
objectspace,
*args,
) -> None:
self.objectspace = objectspace self.objectspace = objectspace
self.uniq_overrides = [] self.uniq_overrides = []
if 'network_type' not in self.objectspace.types: if 'network_type' not in self.objectspace.types:

View File

@ -24,8 +24,8 @@ You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
""" """
from ..i18n import _ from rougail.i18n import _
from ..error import DictConsistencyError from rougail.error import DictConsistencyError
class TargetAnnotator: class TargetAnnotator:

View File

@ -24,16 +24,18 @@ You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
""" """
from .variable import Walk from rougail.annotator.variable import Walk
from ..i18n import _ from rougail.i18n import _
from ..error import DictConsistencyError from rougail.error import DictConsistencyError
class ValueAnnotator(Walk): # pylint: disable=R0903 class Annotator(Walk): # pylint: disable=R0903
"""Annotate value """Annotate value
""" """
level = 70
def __init__(self, def __init__(self,
objectspace, objectspace,
*args,
) -> None: ) -> None:
if not hasattr(objectspace.space, 'variables'): if not hasattr(objectspace.space, 'variables'):
return return

View File

@ -25,9 +25,9 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
""" """
from ..i18n import _ from rougail.i18n import _
from ..error import DictConsistencyError from rougail.error import DictConsistencyError
from ..objspace import convert_boolean from rougail.objspace import convert_boolean
CONVERT_OPTION = {'number': dict(opttype="IntOption", func=int), CONVERT_OPTION = {'number': dict(opttype="IntOption", func=int),
@ -111,11 +111,13 @@ class Walk:
yield from self._get_families(fam) yield from self._get_families(fam)
class VariableAnnotator(Walk): # pylint: disable=R0903 class Annotator(Walk): # pylint: disable=R0903
"""Annotate variable """Annotate variable
""" """
level = 30
def __init__(self, def __init__(self,
objectspace, objectspace,
*args,
): ):
if not hasattr(objectspace.space, 'variables'): if not hasattr(objectspace.space, 'variables'):
return return

View File

@ -43,6 +43,7 @@ RougailConfig = {'dictionaries_dir': [join(ROUGAILROOT, 'dictionaries')],
'variable_namespace': 'rougail', 'variable_namespace': 'rougail',
'auto_freeze_variable': 'server_deployed', 'auto_freeze_variable': 'server_deployed',
'internal_functions': [], 'internal_functions': [],
'extra_annotators': [],
'modes_level': ['basic', 'normal', 'expert'], 'modes_level': ['basic', 'normal', 'expert'],
'default_family_mode': 'basic', 'default_family_mode': 'basic',
'default_variable_mode': 'normal', 'default_variable_mode': 'normal',

View File

@ -83,7 +83,7 @@
<!ATTLIST family mode CDATA #IMPLIED> <!ATTLIST family mode CDATA #IMPLIED>
<!ATTLIST family hidden (True|False) "False"> <!ATTLIST family hidden (True|False) "False">
<!ATTLIST family dynamic CDATA #IMPLIED> <!ATTLIST family dynamic CDATA #IMPLIED>
<!ATTLIST family public CDATA #IMPLIED> <!ATTLIST family provider CDATA #IMPLIED>
<!ELEMENT variable (value*)> <!ELEMENT variable (value*)>
<!ATTLIST variable name CDATA #REQUIRED> <!ATTLIST variable name CDATA #REQUIRED>
@ -102,7 +102,7 @@
<!ATTLIST variable remove_check (True|False) "False"> <!ATTLIST variable remove_check (True|False) "False">
<!ATTLIST variable remove_condition (True|False) "False"> <!ATTLIST variable remove_condition (True|False) "False">
<!ATTLIST variable remove_fill (True|False) "False"> <!ATTLIST variable remove_fill (True|False) "False">
<!ATTLIST variable public CDATA #IMPLIED> <!ATTLIST variable provider CDATA #IMPLIED>
<!ATTLIST variable test CDATA #IMPLIED> <!ATTLIST variable test CDATA #IMPLIED>
<!ELEMENT value (#PCDATA)> <!ELEMENT value (#PCDATA)>

View File

@ -122,10 +122,11 @@ class RougailLeader:
For examples: %%leader, %%leader[0].follower1 For examples: %%leader, %%leader[0].follower1
""" """
def __init__(self, def __init__(self,
leader_name,
value, value,
) -> None: ) -> None:
self._value = value self._value = value
self._follower = {} self._follower = {leader_name: value}
def __getitem__(self, index): def __getitem__(self, index):
"""Get a leader.follower at requested index. """Get a leader.follower at requested index.
@ -393,8 +394,9 @@ class RougailBaseTemplate:
if await option.option.isleadership(): if await option.option.isleadership():
for idx, suboption in enumerate(await option.list('all')): for idx, suboption in enumerate(await option.list('all')):
if idx == 0: if idx == 0:
leader = RougailLeader(await suboption.value.get())
leader_name = await suboption.option.name() leader_name = await suboption.option.name()
leader = RougailLeader(leader_name, await suboption.value.get())
leadership_name = await option.option.name()
if is_variable_namespace: if is_variable_namespace:
self.rougail_variables_dict[await suboption.option.name()] = leader self.rougail_variables_dict[await suboption.option.name()] = leader
else: else:
@ -402,7 +404,7 @@ class RougailBaseTemplate:
await suboption.option.name(), await suboption.option.name(),
await suboption.option.path(), await suboption.option.path(),
) )
variables[leader_name] = leader variables[leadership_name] = leader
else: else:
if is_service_namespace == 'root': if is_service_namespace == 'root':
new_is_service_namespace = 'service_name' new_is_service_namespace = 'service_name'

View File

@ -0,0 +1,19 @@
<?xml version='1.0' encoding='UTF-8'?>
<rougail version="0.9">
<services>
<service name='test'>
<file>/etc/mailname</file>
<file engine="jinja2">/etc/mailname2</file>
</service>
</services>
<variables>
<family name="general" description="général">
<variable name="mode_conteneur_actif" type="string" description="No change" hidden="True">
<value>non</value>
</variable>
<variable name="activer_ejabberd" type="string" description="No change" hidden="True">
<value>non</value>
</variable>
</family>
</variables>
</rougail>

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<rougail version="0.9">
<variables>
<family name='ejabberd'>
<variable name="description" type="string" multi="True">
<value>test</value>
</variable>
<variable name="mode" type="string">
<value>pre</value>
</variable>
</family>
</variables>
<constraints>
<group leader="extra.ejabberd.description" name="new_name">
<follower>mode</follower>
</group>
</constraints>
</rougail>

View File

@ -0,0 +1,48 @@
{
"rougail.general.mode_conteneur_actif": {
"owner": "default",
"value": "non"
},
"rougail.general.activer_ejabberd": {
"owner": "default",
"value": "non"
},
"extra.ejabberd.new_name.description": {
"owner": "default",
"value": [
"test"
]
},
"extra.ejabberd.new_name.mode": {
"owner": [
"default"
],
"value": [
"pre"
]
},
"services.test.files.mailname.name": {
"owner": "default",
"value": "/etc/mailname"
},
"services.test.files.mailname.activate": {
"owner": "default",
"value": true
},
"services.test.files.mailname2.name": {
"owner": "default",
"value": "/etc/mailname2"
},
"services.test.files.mailname2.activate": {
"owner": "default",
"value": true
},
"services.test.activate": {
"owner": "default",
"value": true
},
"services.test.manage": {
"owner": "default",
"value": true
}
}

View File

@ -0,0 +1,16 @@
{
"rougail.general.mode_conteneur_actif": "non",
"rougail.general.activer_ejabberd": "non",
"extra.ejabberd.new_name.description": [
{
"extra.ejabberd.new_name.description": "test",
"extra.ejabberd.new_name.mode": "pre"
}
],
"services.test.files.mailname.name": "/etc/mailname",
"services.test.files.mailname.activate": true,
"services.test.files.mailname2.name": "/etc/mailname2",
"services.test.files.mailname2.activate": true,
"services.test.activate": true,
"services.test.manage": true
}

View File

@ -0,0 +1,48 @@
{
"rougail.general.mode_conteneur_actif": {
"owner": "default",
"value": "non"
},
"rougail.general.activer_ejabberd": {
"owner": "default",
"value": "non"
},
"extra.ejabberd.new_name.description": {
"owner": "default",
"value": [
"test"
]
},
"extra.ejabberd.new_name.mode": {
"owner": [
"default"
],
"value": [
"pre"
]
},
"services.test.files.mailname.name": {
"owner": "default",
"value": "/etc/mailname"
},
"services.test.files.mailname.activate": {
"owner": "default",
"value": true
},
"services.test.files.mailname2.name": {
"owner": "default",
"value": "/etc/mailname2"
},
"services.test.files.mailname2.activate": {
"owner": "default",
"value": true
},
"services.test.activate": {
"owner": "default",
"value": true
},
"services.test.manage": {
"owner": "default",
"value": true
}
}

View File

@ -0,0 +1,11 @@
contain test
1
leader: test
follower: pre
supeq
sup
diff
testpre
pretest
leader2: test
follower2: pre

View File

@ -0,0 +1,11 @@
contain test
1
leader: test
follower: pre
supeq
sup
diff
testpre
pretest
leader2: test
follower2: pre

View File

@ -0,0 +1,4 @@
C /etc/mailname 0644 root root - /usr/local/lib/etc/mailname
z /etc/mailname - - - - -
C /etc/mailname2 0644 root root - /usr/local/lib/etc/mailname2
z /etc/mailname2 - - - - -

View File

@ -0,0 +1,37 @@
from importlib.machinery import SourceFileLoader
from importlib.util import spec_from_loader, module_from_spec
loader = SourceFileLoader('func', 'tests/dictionaries/../eosfunc/test.py')
spec = spec_from_loader(loader.name, loader)
func = module_from_spec(spec)
loader.exec_module(func)
for key, value in dict(locals()).items():
if key != ['SourceFileLoader', 'func']:
setattr(func, key, value)
try:
from tiramisu3 import *
except:
from tiramisu import *
option_3 = StrOption(name="mode_conteneur_actif", doc="No change", default="non", properties=frozenset({"force_default_on_freeze", "frozen", "hidden", "mandatory", "normal"}))
option_4 = StrOption(name="activer_ejabberd", doc="No change", default="non", properties=frozenset({"force_default_on_freeze", "frozen", "hidden", "mandatory", "normal"}))
option_2 = OptionDescription(name="general", doc="général", children=[option_3, option_4], properties=frozenset({"normal"}))
option_1 = OptionDescription(name="rougail", doc="rougail", children=[option_2])
option_8 = StrOption(name="description", doc="description", multi=True, default=['test'], properties=frozenset({"mandatory"}))
option_9 = StrOption(name="mode", doc="mode", multi=True, default_multi="pre", properties=frozenset({"mandatory", "normal"}))
option_7 = Leadership(name="new_name", doc="new_name", children=[option_8, option_9], properties=frozenset({"normal"}))
option_6 = OptionDescription(name="ejabberd", doc="ejabberd", children=[option_7], properties=frozenset({"normal"}))
option_5 = OptionDescription(name="extra", doc="extra", children=[option_6])
option_14 = FilenameOption(name="name", doc="name", default="/etc/mailname")
option_15 = BoolOption(name="activate", doc="activate", default=True)
option_13 = OptionDescription(name="mailname", doc="mailname", children=[option_14, option_15])
option_13.impl_set_information('source', "mailname")
option_17 = FilenameOption(name="name", doc="name", default="/etc/mailname2")
option_18 = BoolOption(name="activate", doc="activate", default=True)
option_16 = OptionDescription(name="mailname2", doc="mailname2", children=[option_17, option_18])
option_16.impl_set_information('engine', "jinja2")
option_16.impl_set_information('source', "mailname2")
option_12 = OptionDescription(name="files", doc="files", children=[option_13, option_16])
option_19 = BoolOption(name="activate", doc="activate", default=True)
option_20 = BoolOption(name="manage", doc="manage", default=True)
option_11 = OptionDescription(name="test", doc="test", children=[option_12, option_19, option_20])
option_10 = OptionDescription(name="services", doc="services", children=[option_11], properties=frozenset({"hidden"}))
option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[option_1, option_5, option_10])

View File

@ -0,0 +1,35 @@
%if 'test' in %%extra.ejabberd.new_name
contain test
%end if
%%len(%%extra.ejabberd.new_name)
%if 'a' in %%extra.ejabberd.new_name
contain a
%end if
%for %%description in %%extra.ejabberd.new_name
leader: %%description
follower: %%description.mode
%if %%description <= %%description.mode
infeq
%end if
%if %%description >= %%description.mode
supeq
%end if
%if %%description < %%description.mode
inf
%end if
%if %%description > %%description.mode
sup
%end if
%if %%description == %%description.mode
eq
%end if
%if %%description != %%description.mode
diff
%end if
%set %%var = %%description + %%description.mode
%%var
%set %%var = %%description.mode + %%description
%%var
%end for
leader2: %%extra.ejabberd.new_name[0].description
follower2: %%extra.ejabberd.new_name[0].mode

View File

@ -0,0 +1,33 @@
{% if 'test' in extra.ejabberd.new_name -%}
contain test
{% endif -%}
{{ extra.ejabberd.new_name |length }}
{% if 'a' in extra.ejabberd.new_name -%}
contain a
{% endif -%}
{% for description in extra.ejabberd.new_name -%}
leader: {{ description }}
follower: {{ description.mode }}
{% if description <= description.mode -%}
infeq
{% endif -%}
{% if description >= description.mode -%}
supeq
{% endif -%}
{% if description < description.mode -%}
inf
{% endif -%}
{% if description > description.mode -%}
sup
{% endif -%}
{% if description == description.mode -%}
eq
{% endif -%}
{% if description != description.mode -%}
diff
{% endif -%}
{{ description + description.mode }}
{{ description.mode + description }}
{% endfor -%}
leader2: {{ extra.ejabberd.new_name[0].description }}
follower2: {{ extra.ejabberd.new_name[0].mode }}