simplify objectspace

This commit is contained in:
Emmanuel Garette 2020-12-23 17:36:50 +01:00
parent 6c6746c58f
commit ccc6924866
16 changed files with 207 additions and 325 deletions

View File

@ -1059,7 +1059,7 @@ class ConstraintAnnotator:
for idx in indexes:
fill = fills[idx]
# test if it's redefined calculation
if fill.target in targets and not fill.redefine:
if fill.target in targets:
xmlfiles = self.objectspace.display_xmlfiles(fill.xmlfiles)
raise DictConsistencyError(_(f'A fill already exists for the target of "{fill.target}" created in {xmlfiles}'))
targets.append(fill.target)

View File

@ -50,21 +50,21 @@
<!ATTLIST service manage (True|False) "True">
<!ELEMENT port (#PCDATA)>
<!ATTLIST port port_type (PortOption|SymLinkOption|variable) "PortOption">
<!ATTLIST port port_type (PortOption|variable) "PortOption">
<!ATTLIST port portlist CDATA #IMPLIED >
<!ATTLIST port protocol (tcp|udp) "tcp">
<!ELEMENT ip (#PCDATA)>
<!ATTLIST ip iplist CDATA #IMPLIED >
<!ATTLIST ip ip_type (NetworkOption|SymLinkOption|variable) "NetworkOption">
<!ATTLIST ip interface_type (UnicodeOption|SymLinkOption|variable) "UnicodeOption">
<!ATTLIST ip ip_type (NetworkOption|variable) "NetworkOption">
<!ATTLIST ip interface_type (UnicodeOption|variable) "UnicodeOption">
<!ATTLIST ip interface CDATA #REQUIRED>
<!ATTLIST ip netmask_type (NetmaskOption|SymLinkOption|variable) "NetmaskOption">
<!ATTLIST ip netmask_type (NetmaskOption|variable) "NetmaskOption">
<!ATTLIST ip netmask CDATA "255.255.255.255">
<!ELEMENT file EMPTY>
<!ATTLIST file name CDATA #REQUIRED >
<!ATTLIST file file_type (UnicodeOption|SymLinkOption|variable) "UnicodeOption">
<!ATTLIST file file_type (UnicodeOption|variable) "UnicodeOption">
<!ATTLIST file variable CDATA #IMPLIED>
<!ATTLIST file variable_type (variable) "variable">
<!ATTLIST file source CDATA #IMPLIED>

View File

@ -1,20 +1,25 @@
"""
Creole flattener. Takes a bunch of Creole XML dispatched in differents folders
as an input and outputs a human readable flatened XML
Takes a bunch of Creole XML dispatched in differents folders
as an input and outputs a Tiramisu's file
Sample usage::
eolobj.space_visitor(func)
xml = eolobj.save()
>>> from rougail.objspace import CreoleObjSpace
>>> eolobj = CreoleObjSpace('/usr/share/rougail/rougail.dtd')
>>> eolobj.create_or_populate_from_xml('rougail', ['/usr/share/eole/rougail/dicos'])
>>> eolobj.space_visitor()
>>> eolobj.save('/tmp/rougail_flatened_output.xml')
>>> eolobj.create_or_populate_from_xml('rougail', ['/usr/share/rougail/dicos'])
>>> eolobj.space_visitor('/usr/share/rougail/funcs.py')
>>> tiramisu = eolobj.save()
The CreoleObjSpace
- loads the XML into an internal CreoleObjSpace representation
- visits/annotates the objects
- dumps the object space as XML output into a single XML target
- dumps the object space as Tiramisu string
The visit/annotation stage is a complex step that corresponds to the Creole
procedures.
@ -23,11 +28,9 @@ For example: a variable is redefined and shall be moved to another family
means that a variable1 = Variable() object in the object space who lives in the family1 parent
has to be moved in family2. The visit procedure changes the varable1's object space's parent.
"""
from lxml.etree import Element, SubElement # pylint: disable=E0611
from .i18n import _
from .xmlreflector import XMLReflector
from .annotator import ERASED_ATTRIBUTES, SpaceAnnotator
from .annotator import SpaceAnnotator
from .tiramisureflector import TiramisuReflector
from .utils import normalize_family
from .error import OperationError, SpaceObjShallNotBeUpdated, DictConsistencyError
@ -41,20 +44,8 @@ FORCE_UNREDEFINABLES = ('value',)
# CreoleObjSpace's elements that shall be set to the UnRedefinable type
UNREDEFINABLE = ('multi', 'type')
CONVERT_PROPERTIES = {'auto_save': ['force_store_value'], 'auto_freeze': ['force_store_value', 'auto_freeze']}
RENAME_ATTIBUTES = {'description': 'doc'}
FORCED_TEXT_ELTS_AS_NAME = ('choice', 'property', 'value', 'target')
CONVERT_EXPORT = {'Leadership': 'leader',
'Variable': 'variable',
'Value': 'value',
'Property': 'property',
'Choice': 'choice',
'Param': 'param',
'Check': 'check',
}
# _____________________________________________________________________________
# special types definitions for the Object Space's internal representation
@ -65,6 +56,18 @@ class RootCreoleObject:
self.xmlfiles = xmlfiles
class Atom(RootCreoleObject):
pass
class Redefinable(RootCreoleObject):
pass
class UnRedefinable(RootCreoleObject):
pass
class CreoleObjSpace:
"""DOM XML reflexion free internal representation of a Creole Dictionary
"""
@ -77,11 +80,6 @@ class CreoleObjSpace:
an Object Space's atom object is present only once in the
object space's tree
"""
Atom = type('Atom', (RootCreoleObject,), dict())
"A variable that can't be redefined"
Redefinable = type('Redefinable', (RootCreoleObject,), dict())
"A variable can be redefined"
UnRedefinable = type('UnRedefinable', (RootCreoleObject,), dict())
def __init__(self, dtdfilename): # pylint: disable=R0912
@ -95,7 +93,6 @@ class CreoleObjSpace:
self.xmlreflector = XMLReflector()
self.xmlreflector.parse_dtd(dtdfilename)
self.redefine_variables = None
self.fill_removed = None
self.check_removed = None
self.condition_removed = None
@ -116,25 +113,25 @@ class CreoleObjSpace:
for dtd_elt in self.xmlreflector.dtd.iterelements():
attrs = {}
if dtd_elt.name in FORCE_REDEFINABLES:
clstype = self.Redefinable
clstype = Redefinable
elif not dtd_elt.attributes() and dtd_elt.name not in FORCE_UNREDEFINABLES:
clstype = Atom
else:
clstype = self.UnRedefinable
atomic = dtd_elt.name not in FORCE_UNREDEFINABLES and dtd_elt.name not in FORCE_REDEFINABLES
clstype = UnRedefinable
forced_text_elt = dtd_elt.type == 'mixed'
for dtd_attr in dtd_elt.iterattributes():
atomic = False
if set(dtd_attr.itervalues()) == set(['True', 'False']):
if set(dtd_attr.itervalues()) == {'True', 'False'}:
# it's a boolean
self.booleans_attributs.append(dtd_attr.name)
if dtd_attr.default_value:
# set default value for this attribute
default_value = dtd_attr.default_value
if dtd_attr.name in self.booleans_attributs:
default_value = self.convert_boolean(dtd_attr.default_value)
default_value = self.convert_boolean(default_value)
attrs[dtd_attr.name] = default_value
if dtd_attr.name == 'redefine':
# has a redefine attribute, so it's a Redefinable object
clstype = self.Redefinable
clstype = Redefinable
if dtd_attr.name == 'name' and forced_text_elt:
# child.text should be transform has a "name" attribute
self.forced_text_elts.add(dtd_elt.name)
@ -142,22 +139,19 @@ class CreoleObjSpace:
if forced_text_elt is True:
self.forced_text_elts_as_name.add(dtd_elt.name)
if atomic:
# has any attribute so it's an Atomic object
clstype = self.Atom
# create ObjectSpace object
setattr(self, dtd_elt.name, type(dtd_elt.name.capitalize(), (clstype,), attrs))
def create_or_populate_from_xml(self,
namespace,
xmlfolders):
xmlfolders,
):
"""Parses a bunch of XML files
populates the CreoleObjSpace
"""
for xmlfile, document in self.xmlreflector.load_xml_from_folders(xmlfolders):
self.redefine_variables = []
self.fill_removed = []
self.check_removed = []
self.condition_removed = []
self.xml_parse_document(xmlfile,
@ -175,43 +169,43 @@ class CreoleObjSpace:
"""Parses a Creole XML file
populates the CreoleObjSpace
"""
# var to check unique family name in a XML file
family_names = []
for child in document:
# this index enables us to reorder objects
self.index += 1
# doesn't proceed the XML commentaries
if not isinstance(child.tag, str):
# doesn't proceed the XML commentaries
continue
if child.tag == 'family':
if child.attrib['name'] in family_names:
raise DictConsistencyError(_(f'Family "{child.attrib["name"]}" is set several times in "{xmlfile}"'))
family_names.append(child.attrib['name'])
if child.tag == 'variables':
# variables has no name, so force namespace name
child.attrib['name'] = namespace
if child.tag == 'value' and child.text == None:
# FIXME should not be here
if child.tag == 'value' and child.text is None:
continue
# variable objects creation
try:
variableobj = self.generate_variableobj(xmlfile,
variableobj = self.get_variableobj(xmlfile,
child,
space,
namespace,
)
except SpaceObjShallNotBeUpdated:
continue
self.set_text_to_obj(child,
self.index += 1
self.set_text(child,
variableobj,
)
self.set_xml_attributes_to_obj(xmlfile,
self.set_attributes(xmlfile,
child,
variableobj,
)
self.variableobj_tree_visitor(child,
self.remove(child,
variableobj,
namespace,
)
self.fill_variableobj_path_attribute(space,
self.set_path(space,
child,
namespace,
document,
@ -220,6 +214,7 @@ class CreoleObjSpace:
self.add_to_tree_structure(variableobj,
space,
child,
namespace,
)
if list(child) != []:
self.xml_parse_document(xmlfile,
@ -228,34 +223,32 @@ class CreoleObjSpace:
namespace,
)
def generate_variableobj(self,
xmlfile,
child,
def get_variableobj(self,
xmlfile: str,
child: list,
space,
namespace,
):
"""
instanciates or creates Creole Object Subspace objects
"""
variableobj = getattr(self, child.tag)(xmlfile)
if isinstance(variableobj, self.Redefinable):
variableobj = self.create_or_update_redefinable_object(xmlfile,
obj = getattr(self, child.tag)
if Redefinable in obj.__mro__:
return self.create_or_update_redefinable_object(xmlfile,
child.attrib,
space,
child,
namespace,
)
elif isinstance(variableobj, self.Atom) and child.tag in vars(space):
# instanciates an object from the CreoleObjSpace's builtins types
# example : child.tag = constraints -> a self.Constraints() object is created
# this Atom instance has to be a singleton here
elif Atom in obj.__mro__:
if child.tag in vars(space):
# Atom instance has to be a singleton here
# we do not re-create it, we reuse it
variableobj = getattr(space, child.tag)
self.create_tree_structure(space,
child,
variableobj,
)
return variableobj
return getattr(space, child.tag)
return obj(xmlfile)
if child.tag not in vars(space):
setattr(space, child.tag, [])
return obj(xmlfile)
def create_or_update_redefinable_object(self,
xmlfile,
@ -264,59 +257,38 @@ class CreoleObjSpace:
child,
namespace,
):
"""Creates or retrieves the space object that corresponds
to the `child` XML object
Two attributes of the `child` XML object are important:
- with the `redefine` boolean flag attribute we know whether
the corresponding space object shall be created or updated
- `True` means that the corresponding space object shall be updated
- `False` means that the corresponding space object shall be created
- with the `exists` boolean flag attribute we know whether
the corresponding space object shall be created
(or nothing -- that is the space object isn't modified)
- `True` means that the corresponding space object shall be created
- `False` means that the corresponding space object is not updated
In the special case `redefine` is True and `exists` is False,
we create the corresponding space object if it doesn't exist
and we update it if it exists.
:return: the corresponding space object of the `child` XML object
"""
if child.tag in self.forced_text_elts_as_name:
name = child.text
else:
name = subspace['name']
if child.tag == 'family':
name = normalize_family(name)
existed_var = self.is_already_exists(name,
existed_var = self.get_existed_obj(name,
space,
child,
namespace,
)
if existed_var:
# if redefine is set to object, default value is False
# otherwise it's always a redefinable object
default_redefine = child.tag in FORCE_REDEFINABLES
redefine = self.convert_boolean(subspace.get('redefine', default_redefine))
exists = self.convert_boolean(subspace.get('exists', True))
if redefine is True:
existed_var.xmlfiles.append(xmlfile)
return self.translate_in_space(name,
space,
child,
namespace,
)
elif exists is False:
return existed_var
exists = self.convert_boolean(subspace.get('exists', True))
if exists is False:
raise SpaceObjShallNotBeUpdated()
xmlfiles = self.display_xmlfiles(existed_var.xmlfiles)
raise DictConsistencyError(_(f'"{child.tag}" named "{name}" cannot be re-created in "{xmlfile}", already defined in {xmlfiles}'))
redefine = self.convert_boolean(subspace.get('redefine', False))
# if this object must only be modified if object already exists
exists = self.convert_boolean(subspace.get('exists', False))
if redefine is False or exists is True:
if exists is True:
raise SpaceObjShallNotBeUpdated()
redefine = self.convert_boolean(subspace.get('redefine', False))
if redefine is False:
if child.tag not in vars(space):
setattr(space, child.tag, {})
return getattr(self, child.tag)(xmlfile)
raise DictConsistencyError(_(f'Redefined object in "{xmlfile}": "{name}" does not exist yet'))
@ -327,32 +299,7 @@ class CreoleObjSpace:
return '"' + xmlfiles[0] + '"'
return '"' + '", "'.join(xmlfiles[:-1]) + '"' + ' and ' + '"' + xmlfiles[-1] + '"'
def create_tree_structure(self,
space,
child,
variableobj,
): # pylint: disable=R0201
"""
Builds the tree structure of the object space here
we set services attributes in order to be populated later on
for example::
space = Family()
space.variable = dict()
another example:
space = Variable()
space.value = list()
"""
if child.tag not in vars(space):
if isinstance(variableobj, self.Redefinable):
setattr(space, child.tag, dict())
elif isinstance(variableobj, self.UnRedefinable):
setattr(space, child.tag, [])
elif not isinstance(variableobj, self.Atom): # pragma: no cover
raise OperationError(_("Creole object {} "
"has a wrong type").format(type(variableobj)))
def is_already_exists(self,
def get_existed_obj(self,
name: str,
space: str,
child,
@ -362,6 +309,12 @@ class CreoleObjSpace:
if namespace != Config['variable_namespace']:
name = space.path + '.' + name
if self.paths.path_is_defined(name):
old_family_name = self.paths.get_variable_family_name(name)
if namespace != Config['variable_namespace']:
old_family_name = namespace + '.' + old_family_name
if space.path != old_family_name:
xmlfiles = self.display_xmlfiles(space.xmlfiles)
raise DictConsistencyError(_(f'Variable was previously create in family "{old_family_name}", now it is in "{space.path}" in {xmlfiles}'))
return self.paths.get_variable_obj(name)
return
children = getattr(space, child.tag, {})
@ -377,49 +330,59 @@ class CreoleObjSpace:
return True
elif value == 'False':
return False
else:
raise TypeError(_('{} is not True or False').format(value)) # pragma: no cover
def translate_in_space(self,
name,
family,
variable,
namespace,
def set_text(self,
child,
variableobj,
):
if not isinstance(family, self.family): # pylint: disable=E1101
return getattr(family, variable.tag)[name]
if namespace == Config['variable_namespace']:
path = name
if child.text is None:
return
text = child.text.strip()
if not text:
return
if child.tag in self.forced_text_elts_as_name:
variableobj.name = text
else:
path = family.path + '.' + name
old_family_name = self.paths.get_variable_family_name(path)
if family.path == old_family_name:
return getattr(family, variable.tag)[name]
old_family = self.space.variables[namespace].family[old_family_name] # pylint: disable=E1101
variable_obj = old_family.variable[name]
del old_family.variable[name]
if 'variable' not in vars(family):
family.variable = dict()
family.variable[name] = variable_obj
self.paths.add_variable(namespace,
name,
family.name,
False,
variable_obj,
)
return variable_obj
variableobj.text = text
def remove_fill(self, name): # pylint: disable=C0111
if hasattr(self.space, 'constraints') and hasattr(self.space.constraints, 'fill'):
remove_fills= []
for idx, fill in enumerate(self.space.constraints.fill): # pylint: disable=E1101
if hasattr(fill, 'target') and fill.target == name:
remove_fills.append(idx)
def set_attributes(self,
xmlfile,
child,
variableobj,
):
redefine = self.convert_boolean(child.attrib.get('redefine', False))
if redefine and child.tag == 'variable':
# delete old values
has_value = hasattr(variableobj, 'value')
if has_value and len(child) != 0:
del variableobj.value
for attr, val in child.attrib.items():
if redefine and attr in UNREDEFINABLE:
xmlfiles = self.display_xmlfiles(variableobj.xmlfiles[:-1])
raise DictConsistencyError(_(f'cannot redefine attribute "{attr}" for variable "{child.attrib["name"]}" in "{xmlfile}", already defined in {xmlfiles}'))
if attr in self.booleans_attributs:
val = self.convert_boolean(val)
if attr == 'name' and getattr(variableobj, 'name', None):
# do not redefine name
continue
setattr(variableobj, attr, val)
remove_fills = list(set(remove_fills))
remove_fills.sort(reverse=True)
for idx in remove_fills:
self.space.constraints.fill.pop(idx) # pylint: disable=E1101
def remove(self,
child,
variableobj,
):
"""Creole object tree manipulations
"""
if child.tag == 'variable':
if child.attrib.get('remove_check', False):
self.remove_check(variableobj.name)
if child.attrib.get('remove_condition', False):
self.remove_condition(variableobj.name)
if child.attrib.get('remove_fill', False):
self.remove_fill(variableobj.name)
if child.tag == 'fill' and child.attrib['target'] in self.redefine_variables:
self.remove_fill(child.attrib['target'])
def remove_check(self, name): # pylint: disable=C0111
if hasattr(self.space, 'constraints') and hasattr(self.space.constraints, 'check'):
@ -441,83 +404,19 @@ class CreoleObjSpace:
for idx in remove_conditions:
del self.space.constraints.condition[idx]
def add_to_tree_structure(self,
variableobj,
space,
child,
): # pylint: disable=R0201
if isinstance(variableobj, self.Redefinable):
name = variableobj.name
if child.tag == 'family':
name = normalize_family(name)
getattr(space, child.tag)[name] = variableobj
elif isinstance(variableobj, self.UnRedefinable):
getattr(space, child.tag).append(variableobj)
else:
setattr(space, child.tag, variableobj)
def remove_fill(self, name): # pylint: disable=C0111
if hasattr(self.space, 'constraints') and hasattr(self.space.constraints, 'fill'):
remove_fills= []
for idx, fill in enumerate(self.space.constraints.fill): # pylint: disable=E1101
if hasattr(fill, 'target') and fill.target == name:
remove_fills.append(idx)
def set_text_to_obj(self,
child,
variableobj,
):
if child.text is None:
text = None
else:
text = child.text.strip()
if text:
if child.tag in self.forced_text_elts_as_name:
variableobj.name = text
else:
variableobj.text = text
remove_fills = list(set(remove_fills))
remove_fills.sort(reverse=True)
for idx in remove_fills:
self.space.constraints.fill.pop(idx) # pylint: disable=E1101
def set_xml_attributes_to_obj(self,
xmlfile,
child,
variableobj,
):
redefine = self.convert_boolean(child.attrib.get('redefine', False))
has_value = hasattr(variableobj, 'value')
if redefine is True and child.tag == 'variable' and has_value and len(child) != 0:
del variableobj.value
for attr, val in child.attrib.items():
if redefine and attr in UNREDEFINABLE:
# UNREDEFINABLE concerns only 'variable' node so we can fix name
# to child.attrib['name']
name = child.attrib['name']
xmlfiles = self.display_xmlfiles(variableobj.xmlfiles[:-1])
raise DictConsistencyError(_(f'cannot redefine attribute "{attr}" for variable "{name}" in "{xmlfile}", already defined in {xmlfiles}'))
if attr in self.booleans_attributs:
val = self.convert_boolean(val)
if not (attr == 'name' and getattr(variableobj, 'name', None) != None):
setattr(variableobj, attr, val)
keys = list(vars(variableobj).keys())
def variableobj_tree_visitor(self,
child,
variableobj,
namespace,
):
"""Creole object tree manipulations
"""
if child.tag == 'variable':
if child.attrib.get('remove_check', False):
self.remove_check(variableobj.name)
if child.attrib.get('remove_condition', False):
self.remove_condition(variableobj.name)
if child.attrib.get('remove_fill', False):
self.remove_fill(variableobj.name)
if child.tag == 'fill':
# if variable is a redefine in current dictionary
# XXX not working with variable not in variable and in leader/followers
variableobj.redefine = child.attrib['target'] in self.redefine_variables
if child.attrib['target'] in self.redefine_variables and child.attrib['target'] not in self.fill_removed:
self.remove_fill(child.attrib['target'])
self.fill_removed.append(child.attrib['target'])
if not hasattr(variableobj, 'index'):
variableobj.index = self.index
variableobj.namespace = namespace
def fill_variableobj_path_attribute(self,
def set_path(self,
space,
child,
namespace,
@ -526,8 +425,6 @@ class CreoleObjSpace:
): # pylint: disable=R0913
"""Fill self.paths attributes
"""
if isinstance(space, self.help): # pylint: disable=E1101
return
if child.tag == 'variable':
family_name = document.attrib['name']
family_name = normalize_family(family_name)
@ -554,6 +451,25 @@ class CreoleObjSpace:
)
variableobj.path = self.paths.get_family_path(family_name, namespace)
def add_to_tree_structure(self,
variableobj,
space,
child,
namespace,
): # pylint: disable=R0201
if not hasattr(variableobj, 'index'):
variableobj.index = self.index
variableobj.namespace = namespace
if isinstance(variableobj, Redefinable):
name = variableobj.name
if child.tag == 'family':
name = normalize_family(name)
getattr(space, child.tag)[name] = variableobj
elif isinstance(variableobj, UnRedefinable):
getattr(space, child.tag).append(variableobj)
else:
setattr(space, child.tag, variableobj)
def space_visitor(self, eosfunc_file): # pylint: disable=C0111
self.funcs_path = eosfunc_file
SpaceAnnotator(self, eosfunc_file)

View File

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

View File

@ -1,16 +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 = ChoiceOption(properties=frozenset({'force_default_on_freeze', 'frozen', 'hidden', 'mandatory', 'normal'}), name='mode_conteneur_actif', doc='No change', multi=False, default='non', values=('oui', 'non'))
option_2 = OptionDescription(name='general', doc='general', properties=frozenset({'normal'}), children=[option_3])
option_5 = ChoiceOption(properties=frozenset({'force_default_on_freeze', 'frozen', 'hidden', 'mandatory', 'normal'}), name='mode_conteneur_actif1', doc='No change', multi=False, default='non', values=('oui', 'non'))
option_4 = OptionDescription(name='other', doc='other', 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

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

View File

@ -1,16 +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 = ChoiceOption(properties=frozenset({'force_default_on_freeze', 'frozen', 'hidden', 'mandatory', 'normal'}), name='mode_conteneur_actif', doc='No change', multi=False, default='non', values=('oui', 'non'))
option_2 = OptionDescription(name='general', doc='Général', properties=frozenset({'normal'}), children=[option_3])
option_5 = ChoiceOption(properties=frozenset({'force_default_on_freeze', 'frozen', 'hidden', 'mandatory', 'normal'}), name='mode_conteneur_actif1', doc='No change', multi=False, default='non', values=('oui', 'non'))
option_4 = OptionDescription(name='otherwithe', doc='Otherwithé', 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

@ -12,9 +12,9 @@ option_3 = ChoiceOption(properties=frozenset({'force_default_on_freeze', 'frozen
option_4 = ChoiceOption(properties=frozenset({'force_default_on_freeze', 'frozen', 'hidden', 'mandatory', 'normal'}), name='activer_ejabberd', doc='No change', multi=False, default='non', values=('oui', '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 = 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 = ChoiceOption(properties=frozenset({'mandatory', 'normal'}), name='mode', doc='mode', multi=False, default='pre', values=('pre', 'post'))
option_9 = StrOption(properties=frozenset({'force_default_on_freeze', 'frozen', 'hidden', 'mandatory', 'normal'}), name='description', doc='description', multi=False, default='Exportation de la base de ejabberd')
option_7 = StrOption(properties=frozenset({'force_default_on_freeze', 'frozen', 'hidden', '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_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])