Compare commits

..

No commits in common. "f4471c4875f95500b7ce566aa3f15b4ee683f6a9" and "3999969aa0327ff2cd02a08ada2cee126113e4ae" have entirely different histories.

28 changed files with 90 additions and 405 deletions

View File

@ -74,15 +74,15 @@ Voici un exemple de définition d'une variable meneuse et de deux variables mene
</variables>
<constraints>
<group leader="example.family.leader">
<follower>follower1</follower>
<follower>follower2</follower>
<follower>example.family.follower1</follower>
<follower>example.family.follower2</follower>
</group>
</constraints>
```
Le chemin de la variable meneuse est traditionnel, par contre le chemin des variables suiveuses est le chemin relatif de la variable.
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 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.
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.
## Ajout d'une nouvelle variable suiveuse

View File

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

View File

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

View File

@ -27,21 +27,19 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
from typing import List
from rougail.i18n import _
from rougail.error import DictConsistencyError
from ..i18n import _
from ..error import DictConsistencyError
from rougail.annotator.target import TargetAnnotator
from rougail.annotator.param import ParamAnnotator
from rougail.annotator.variable import Walk
from .target import TargetAnnotator
from .param import ParamAnnotator
from .variable import Walk
class Annotator(TargetAnnotator, ParamAnnotator, Walk):
class ConditionAnnotator(TargetAnnotator, ParamAnnotator, Walk):
"""Annotate condition
"""
level = 50
def __init__(self,
objectspace,
*args,
):
self.objectspace = objectspace
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
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
"""
from rougail.i18n import _
from rougail.error import DictConsistencyError
from rougail.annotator.variable import Walk
from ..i18n import _
from ..error import DictConsistencyError
from .variable import Walk
class Mode: # pylint: disable=R0903
@ -43,13 +43,11 @@ class Mode: # pylint: disable=R0903
return other.level < self.level
class Annotator(Walk):
class FamilyAnnotator(Walk):
"""Annotate family
"""
level = 80
def __init__(self,
objectspace,
*args,
):
self.objectspace = objectspace
if not hasattr(self.objectspace.space, 'variables'):
@ -76,7 +74,6 @@ class Annotator(Walk):
def remove_empty_families(self) -> None:
"""Remove all families without any variable
"""
#FIXME pas sous family
for families in self.objectspace.space.variables.values():
removed_families = []
for family_name, family in families.variable.items():

View File

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

View File

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

View File

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

View File

@ -24,23 +24,19 @@ You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
"""
from rougail.i18n import _
from rougail.error import DictConsistencyError
from rougail.annotator.variable import Walk
from ..i18n import _
from ..error import DictConsistencyError
from .variable import Walk
PROPERTIES = ('hidden', 'frozen', 'force_default_on_freeze',
'force_store_value', 'disabled', 'mandatory')
class Annotator(Walk):
class PropertyAnnotator(Walk):
"""Annotate properties
"""
level = 90
def __init__(self,
objectspace,
*args
) -> None:
def __init__(self, objectspace):
self.objectspace = objectspace
if hasattr(self.objectspace.space, '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 typing import Tuple
from rougail.i18n import _
from rougail.utils import normalize_family
from rougail.error import DictConsistencyError
from ..i18n import _
from ..utils import normalize_family
from ..error import DictConsistencyError
# a object's attribute has some annotations
# that shall not be present in the exported (flatened) XML
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']
class Annotator:
class ServiceAnnotator:
"""Manage service's object
for example::
<services>
@ -49,11 +49,7 @@ class Annotator:
</service>
</services>
"""
level = 20
def __init__(self,
objectspace,
*args,
) -> None:
def __init__(self, objectspace):
self.objectspace = objectspace
self.uniq_overrides = []
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
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
"""
from rougail.i18n import _
from rougail.error import DictConsistencyError
from ..i18n import _
from ..error import DictConsistencyError
class TargetAnnotator:

View File

@ -24,18 +24,16 @@ You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
"""
from rougail.annotator.variable import Walk
from .variable import Walk
from rougail.i18n import _
from rougail.error import DictConsistencyError
from ..i18n import _
from ..error import DictConsistencyError
class Annotator(Walk): # pylint: disable=R0903
class ValueAnnotator(Walk): # pylint: disable=R0903
"""Annotate value
"""
level = 70
def __init__(self,
objectspace,
*args,
) -> None:
if not hasattr(objectspace.space, 'variables'):
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
"""
from rougail.i18n import _
from rougail.error import DictConsistencyError
from rougail.objspace import convert_boolean
from ..i18n import _
from ..error import DictConsistencyError
from ..objspace import convert_boolean
CONVERT_OPTION = {'number': dict(opttype="IntOption", func=int),
@ -111,13 +111,11 @@ class Walk:
yield from self._get_families(fam)
class Annotator(Walk): # pylint: disable=R0903
class VariableAnnotator(Walk): # pylint: disable=R0903
"""Annotate variable
"""
level = 30
def __init__(self,
objectspace,
*args,
):
if not hasattr(objectspace.space, 'variables'):
return

View File

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

View File

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

View File

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

View File

@ -1,19 +0,0 @@
<?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

@ -1,19 +0,0 @@
<?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

@ -1,48 +0,0 @@
{
"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

@ -1,16 +0,0 @@
{
"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

@ -1,48 +0,0 @@
{
"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

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

View File

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

View File

@ -1,4 +0,0 @@
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

@ -1,37 +0,0 @@
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

@ -1,35 +0,0 @@
%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

@ -1,33 +0,0 @@
{% 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 }}