manage informations

This commit is contained in:
Emmanuel Garette 2021-01-23 11:57:46 +01:00
parent c05c0b9716
commit 02771b6d73
13 changed files with 75 additions and 55 deletions

View file

@ -39,6 +39,7 @@ class FamilyAnnotator:
self.change_variable_mode() self.change_variable_mode()
self.change_family_mode() self.change_family_mode()
self.dynamic_families() self.dynamic_families()
self.convert_help()
def remove_empty_families(self): def remove_empty_families(self):
"""Remove all families without any variable """Remove all families without any variable
@ -175,3 +176,14 @@ class FamilyAnnotator:
msg = _(f'dynamic family "{family.name}" must be linked ' msg = _(f'dynamic family "{family.name}" must be linked '
f'to multi variable in {xmlfiles}') f'to multi variable in {xmlfiles}')
raise DictConsistencyError(msg, 16) raise DictConsistencyError(msg, 16)
def convert_help(self):
"""Convert variable help
"""
for families in self.objectspace.space.variables.values():
for family in families.family.values():
if hasattr(family, 'help'):
if not hasattr(family, 'information'):
family.information = self.objectspace.information(family.xmlfiles)
family.information.help = family.help
del family.help

View file

@ -11,7 +11,7 @@ from ..error import DictConsistencyError
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', 'reflector_name', 'level', 'remove_fill', 'xmlfiles', 'type', 'reflector_name',
'reflector_object',) 'reflector_object', 'manage')
KEY_TYPE = {'variable': 'symlink', KEY_TYPE = {'variable': 'symlink',
@ -50,14 +50,12 @@ class ServiceAnnotator:
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' self.objectspace.space.services.path = 'services'
families = {} for service_name, service in self.objectspace.space.services.service.items():
for service_name in self.objectspace.space.services.service.keys(): service.information = self.objectspace.information(service.xmlfiles)
service = self.objectspace.space.services.service[service_name] service.information.manage = service.manage
new_service = self.objectspace.service(service.xmlfiles) service.manage = None
new_service.path = f'services.{service_name}' for elttype, values in dict(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)
continue continue
eltname = elttype + 's' eltname = elttype + 's'
path = '.'.join(['services', normalize_family(service_name), eltname]) path = '.'.join(['services', normalize_family(service_name), eltname])
@ -72,10 +70,8 @@ class ServiceAnnotator:
values, values,
path, path,
) )
setattr(new_service, elttype, family) setattr(service, elttype, family)
new_service.doc = new_service.name service.doc = service.name
families[service_name] = new_service
self.objectspace.space.services.service = families
def make_group_from_elts(self, def make_group_from_elts(self,
service_name, service_name,

View file

@ -54,6 +54,7 @@ class VariableAnnotator: # pylint: disable=R0903
self.objectspace = objectspace self.objectspace = objectspace
self.convert_variable() self.convert_variable()
self.convert_test() self.convert_test()
self.convert_help()
def convert_variable(self): def convert_variable(self):
"""convert variable """convert variable
@ -162,16 +163,38 @@ class VariableAnnotator: # pylint: disable=R0903
def _convert_test(self, def _convert_test(self,
variable, variable,
) -> None: ) -> None:
if not hasattr(variable, 'information'):
variable.information = self.objectspace.information(variable.xmlfiles)
if hasattr(variable, 'test'): if hasattr(variable, 'test'):
if not variable.test: if variable.test:
del variable.test values = variable.test.split('|')
return new_values = []
values = variable.test.split('|') for value in values:
new_values = [] if value == '':
for value in values: value = None
if value == '': else:
value = None value = CONVERT_OPTION.get(variable.type, {}).get('func', str)(value)
else: new_values.append(value)
value = CONVERT_OPTION.get(variable.type, {}).get('func', str)(value) variable.information.test = tuple(new_values)
new_values.append(value) del variable.test
variable.test = tuple(new_values)
def convert_help(self):
"""Convert variable help
"""
for families in self.objectspace.space.variables.values():
for family in families.family.values():
if not hasattr(family, 'variable'):
continue
for variable in family.variable.values():
if isinstance(variable, self.objectspace.leadership):
for follower in variable.variable:
self._convert_help(follower)
else:
self._convert_help(variable)
def _convert_help(self,
variable,
) -> None:
if hasattr(variable, 'help'):
variable.information.help = variable.help
del variable.help

View file

@ -17,7 +17,7 @@ FORCE_UNREDEFINABLES = ('value',)
# RougailObjSpace's elements that shall not be modify # RougailObjSpace's elements that shall not be modify
UNREDEFINABLE = ('multi', 'type') UNREDEFINABLE = ('multi', 'type')
# RougailObjSpace's elements that did not created automaticly # RougailObjSpace's elements that did not created automaticly
FORCE_ELEMENTS = ('choice', 'property_', 'leadership') FORCE_ELEMENTS = ('choice', 'property_', 'leadership', 'information')
# XML text are convert has name # XML text are convert has name
FORCED_TEXT_ELTS_AS_NAME = ('choice', 'property', 'value', 'target') FORCED_TEXT_ELTS_AS_NAME = ('choice', 'property', 'value', 'target')

View file

@ -3,12 +3,10 @@ flattened XML specific
""" """
from .config import Config from .config import Config
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', 'manage'] ATTRIBUTES_ORDER = ('name', 'doc', 'default', 'multi', 'properties', 'max_number', 'min_number', 'dynamic', 'opt')
ATTRIBUTES_ORDER = ('name', 'doc', 'default', 'multi')
class Root(): # pylint: disable=R0903 class Root(): # pylint: disable=R0903
@ -180,7 +178,6 @@ class Common:
self.elt = elt self.elt = elt
self.option_name = None self.option_name = None
self.attrib = {} self.attrib = {}
self.informations = {}
self.text = text self.text = text
self.elt.reflector_object = self self.elt.reflector_object = self
@ -228,7 +225,11 @@ class Common:
def populate_informations(self): def populate_informations(self):
"""Populate Tiramisu's informations """Populate Tiramisu's informations
""" """
for key, value in self.informations.items(): if not hasattr(self.elt, 'information'):
return
for key, value in vars(self.elt.information).items():
if key == 'xmlfiles':
continue
if isinstance(value, str): if isinstance(value, str):
value = '"' + value.replace('"', '\"') + '"' value = '"' + value.replace('"', '\"') + '"'
self.text.append(f'{self.option_name}.impl_set_information("{key}", {value})') self.text.append(f'{self.option_name}.impl_set_information("{key}", {value})')
@ -236,17 +237,9 @@ class Common:
def get_attributes(self, space): # pylint: disable=R0201 def get_attributes(self, space): # pylint: disable=R0201
"""Get attributes """Get attributes
""" """
attributes = dir(space)
for attr in ATTRIBUTES_ORDER: for attr in ATTRIBUTES_ORDER:
if attr in attributes: if hasattr(space, attr):
yield attr yield attr
for attr in dir(space):
if attr not in ATTRIBUTES_ORDER:
if not attr.startswith('_') and attr not in ERASED_ATTRIBUTES:
value = getattr(space, attr)
if not isinstance(value, (list, dict)) and \
not value.__class__.__name__ == 'Family':
yield attr
@staticmethod @staticmethod
def get_children(space): def get_children(space):
@ -296,11 +289,7 @@ class Variable(Common):
"""Populate attributes """Populate attributes
""" """
for key in self.get_attributes(self.elt): for key in self.get_attributes(self.elt):
value = getattr(self.elt, key) self.attrib[key] = getattr(self.elt, key)
if key in FORCE_INFORMATIONS:
self.informations[key] = value
else:
self.attrib[key] = value
def parse_children(self): def parse_children(self):
"""Parse children """Parse children
@ -346,6 +335,8 @@ class Variable(Common):
self.calculate_choice(child, self.calculate_choice(child,
choices, choices,
) )
else: # pragma: no cover
raise Exception(f'unknown tag {tag}')
def calculate_choice(self, def calculate_choice(self,
child, child,
@ -475,9 +466,7 @@ class Family(Common):
""" """
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 == 'dynamic':
self.informations[key] = value
elif key == 'dynamic':
dynamic = value.reflector_object.get() dynamic = value.reflector_object.get()
self.attrib['suffixes'] = \ self.attrib['suffixes'] = \
f"Calculation(func.calc_value, Params((ParamOption({dynamic}))))" f"Calculation(func.calc_value, Params((ParamOption({dynamic}))))"

View file

@ -15,6 +15,6 @@ from rougail.tiramisu import ConvertDynOptionDescription
option_3 = StrOption(properties=frozenset({'mandatory', 'normal'}), name='varname', doc='No change', multi=True, default=['val1', 'val2'], default_multi='val2') option_3 = StrOption(properties=frozenset({'mandatory', 'normal'}), name='varname', doc='No change', multi=True, default=['val1', 'val2'], default_multi='val2')
option_2 = OptionDescription(name='general', doc='general', properties=frozenset({'normal'}), children=[option_3]) option_2 = OptionDescription(name='general', doc='general', properties=frozenset({'normal'}), children=[option_3])
option_5 = StrOption(properties=frozenset({'normal'}), name='vardyn', doc='No change', multi=False) option_5 = StrOption(properties=frozenset({'normal'}), name='vardyn', doc='No change', multi=False)
option_4 = ConvertDynOptionDescription(name='dyn', doc='dyn', suffixes=Calculation(func.calc_value, Params((ParamOption(option_3)))), properties=frozenset({'normal'}), children=[option_5]) option_4 = ConvertDynOptionDescription(name='dyn', doc='dyn', properties=frozenset({'normal'}), suffixes=Calculation(func.calc_value, Params((ParamOption(option_3)))), children=[option_5])
option_1 = OptionDescription(name='rougail', doc='rougail', children=[option_2, option_4]) option_1 = OptionDescription(name='rougail', doc='rougail', children=[option_2, option_4])
option_0 = OptionDescription(name='baseoption', doc='baseoption', children=[option_1]) option_0 = OptionDescription(name='baseoption', doc='baseoption', children=[option_1])

View file

@ -15,7 +15,7 @@ from rougail.tiramisu import ConvertDynOptionDescription
option_3 = StrOption(properties=frozenset({'mandatory', 'normal'}), name='varname', doc='No change', multi=True, default=['val1', 'val2'], default_multi='val2') option_3 = StrOption(properties=frozenset({'mandatory', 'normal'}), name='varname', doc='No change', multi=True, default=['val1', 'val2'], default_multi='val2')
option_2 = OptionDescription(name='general', doc='general', properties=frozenset({'normal'}), children=[option_3]) option_2 = OptionDescription(name='general', doc='general', properties=frozenset({'normal'}), children=[option_3])
option_5 = StrOption(properties=frozenset({'mandatory', 'normal'}), name='vardyn', doc='No change', multi=False, default='val') option_5 = StrOption(properties=frozenset({'mandatory', 'normal'}), name='vardyn', doc='No change', multi=False, default='val')
option_4 = ConvertDynOptionDescription(name='dyn', doc='dyn', suffixes=Calculation(func.calc_value, Params((ParamOption(option_3)))), properties=frozenset({'normal'}), children=[option_5]) option_4 = ConvertDynOptionDescription(name='dyn', doc='dyn', properties=frozenset({'normal'}), suffixes=Calculation(func.calc_value, Params((ParamOption(option_3)))), children=[option_5])
option_7 = StrOption(properties=frozenset({'normal'}), name='newvar', doc='No change', multi=False, default=Calculation(func.calc_val, Params((ParamDynOption(option_5, 'val1', option_4, notraisepropertyerror=False, todict=False)), kwargs={}))) option_7 = StrOption(properties=frozenset({'normal'}), name='newvar', doc='No change', multi=False, default=Calculation(func.calc_val, Params((ParamDynOption(option_5, 'val1', option_4, notraisepropertyerror=False, todict=False)), kwargs={})))
option_6 = OptionDescription(name='new', doc='new', properties=frozenset({'normal'}), children=[option_7]) option_6 = OptionDescription(name='new', doc='new', properties=frozenset({'normal'}), children=[option_7])
option_1 = OptionDescription(name='rougail', doc='rougail', children=[option_2, option_4, option_6]) option_1 = OptionDescription(name='rougail', doc='rougail', children=[option_2, option_4, option_6])

View file

@ -16,7 +16,7 @@ option_3 = StrOption(properties=frozenset({'mandatory', 'normal'}), name='varnam
option_2 = OptionDescription(name='general', doc='general', properties=frozenset({'normal'}), children=[option_3]) option_2 = OptionDescription(name='general', doc='general', properties=frozenset({'normal'}), children=[option_3])
option_7 = StrOption(properties=frozenset({'normal'}), name='newvar', doc='No change', multi=False) option_7 = StrOption(properties=frozenset({'normal'}), name='newvar', doc='No change', multi=False)
option_5 = StrOption(properties=frozenset({'mandatory', 'normal', Calculation(calc_value, Params(ParamValue('frozen'), kwargs={'condition': ParamOption(option_7, todict=True), 'expected': ParamValue('non')})), Calculation(calc_value, Params(ParamValue('force_default_on_freeze'), kwargs={'condition': ParamOption(option_7, todict=True), 'expected': ParamValue('non')}))}), name='vardyn', doc='No change', multi=False, default='val') option_5 = StrOption(properties=frozenset({'mandatory', 'normal', Calculation(calc_value, Params(ParamValue('frozen'), kwargs={'condition': ParamOption(option_7, todict=True), 'expected': ParamValue('non')})), Calculation(calc_value, Params(ParamValue('force_default_on_freeze'), kwargs={'condition': ParamOption(option_7, todict=True), 'expected': ParamValue('non')}))}), name='vardyn', doc='No change', multi=False, default='val')
option_4 = ConvertDynOptionDescription(name='dyn', doc='dyn', suffixes=Calculation(func.calc_value, Params((ParamOption(option_3)))), properties=frozenset({'normal', Calculation(calc_value, Params(ParamValue('hidden'), kwargs={'condition': ParamOption(option_7, todict=True), 'expected': ParamValue('non')}))}), children=[option_5]) option_4 = ConvertDynOptionDescription(name='dyn', doc='dyn', properties=frozenset({'normal', Calculation(calc_value, Params(ParamValue('hidden'), kwargs={'condition': ParamOption(option_7, todict=True), 'expected': ParamValue('non')}))}), suffixes=Calculation(func.calc_value, Params((ParamOption(option_3)))), children=[option_5])
option_6 = OptionDescription(name='new', doc='new', properties=frozenset({'normal'}), children=[option_7]) option_6 = OptionDescription(name='new', doc='new', properties=frozenset({'normal'}), children=[option_7])
option_1 = OptionDescription(name='rougail', doc='rougail', children=[option_2, option_4, option_6]) option_1 = OptionDescription(name='rougail', doc='rougail', children=[option_2, option_4, option_6])
option_0 = OptionDescription(name='baseoption', doc='baseoption', children=[option_1]) option_0 = OptionDescription(name='baseoption', doc='baseoption', children=[option_1])

View file

@ -15,7 +15,7 @@ from rougail.tiramisu import ConvertDynOptionDescription
option_3 = StrOption(properties=frozenset({'mandatory', 'normal'}), name='varname', doc='No change', multi=True, default=['val1', 'val2'], default_multi='val2') option_3 = StrOption(properties=frozenset({'mandatory', 'normal'}), name='varname', doc='No change', multi=True, default=['val1', 'val2'], default_multi='val2')
option_2 = OptionDescription(name='general', doc='general', properties=frozenset({'normal'}), children=[option_3]) option_2 = OptionDescription(name='general', doc='general', properties=frozenset({'normal'}), children=[option_3])
option_5 = StrOption(properties=frozenset({'normal'}), name='vardyn', doc='No change', multi=False, default=Calculation(func.calc_val, Params((ParamSuffix()), kwargs={}))) option_5 = StrOption(properties=frozenset({'normal'}), name='vardyn', doc='No change', multi=False, default=Calculation(func.calc_val, Params((ParamSuffix()), kwargs={})))
option_4 = ConvertDynOptionDescription(name='dyn', doc='dyn', suffixes=Calculation(func.calc_value, Params((ParamOption(option_3)))), properties=frozenset({'normal'}), children=[option_5]) option_4 = ConvertDynOptionDescription(name='dyn', doc='dyn', properties=frozenset({'normal'}), suffixes=Calculation(func.calc_value, Params((ParamOption(option_3)))), children=[option_5])
option_7 = StrOption(properties=frozenset({'normal'}), name='newvar', doc='No change', multi=False) option_7 = StrOption(properties=frozenset({'normal'}), name='newvar', doc='No change', multi=False)
option_6 = OptionDescription(name='new', doc='new', properties=frozenset({'normal'}), children=[option_7]) option_6 = OptionDescription(name='new', doc='new', properties=frozenset({'normal'}), children=[option_7])
option_1 = OptionDescription(name='rougail', doc='rougail', children=[option_2, option_4, option_6]) option_1 = OptionDescription(name='rougail', doc='rougail', children=[option_2, option_4, option_6])

View file

@ -15,6 +15,6 @@ from rougail.tiramisu import ConvertDynOptionDescription
option_3 = StrOption(properties=frozenset({'mandatory', 'normal'}), name='varname', doc='No change', multi=True, default=['val1', 'val2'], default_multi='val2') option_3 = StrOption(properties=frozenset({'mandatory', 'normal'}), name='varname', doc='No change', multi=True, default=['val1', 'val2'], default_multi='val2')
option_2 = OptionDescription(name='general', doc='general', properties=frozenset({'normal'}), children=[option_3]) option_2 = OptionDescription(name='general', doc='general', properties=frozenset({'normal'}), children=[option_3])
option_5 = StrOption(properties=frozenset({'normal'}), name='vardyn', doc='No change', multi=False) option_5 = StrOption(properties=frozenset({'normal'}), name='vardyn', doc='No change', multi=False)
option_4 = ConvertDynOptionDescription(name='dyn', doc='Dyn ', suffixes=Calculation(func.calc_value, Params((ParamOption(option_3)))), properties=frozenset({'normal'}), children=[option_5]) option_4 = ConvertDynOptionDescription(name='dyn', doc='Dyn ', properties=frozenset({'normal'}), suffixes=Calculation(func.calc_value, Params((ParamOption(option_3)))), children=[option_5])
option_1 = OptionDescription(name='rougail', doc='rougail', children=[option_2, option_4]) option_1 = OptionDescription(name='rougail', doc='rougail', children=[option_2, option_4])
option_0 = OptionDescription(name='baseoption', doc='baseoption', children=[option_1]) option_0 = OptionDescription(name='baseoption', doc='baseoption', children=[option_1])

View file

@ -15,7 +15,7 @@ from rougail.tiramisu import ConvertDynOptionDescription
option_3 = IntOption(properties=frozenset({'mandatory', 'normal'}), name='varname', doc='No change', multi=True, default=[1, 2], default_multi=2) option_3 = IntOption(properties=frozenset({'mandatory', 'normal'}), name='varname', doc='No change', multi=True, default=[1, 2], default_multi=2)
option_2 = OptionDescription(name='general', doc='general', properties=frozenset({'normal'}), children=[option_3]) option_2 = OptionDescription(name='general', doc='general', properties=frozenset({'normal'}), children=[option_3])
option_5 = StrOption(properties=frozenset({'mandatory', 'normal'}), name='vardyn', doc='No change', multi=False, default='val') option_5 = StrOption(properties=frozenset({'mandatory', 'normal'}), name='vardyn', doc='No change', multi=False, default='val')
option_4 = ConvertDynOptionDescription(name='dyn', doc='dyn', suffixes=Calculation(func.calc_value, Params((ParamOption(option_3)))), properties=frozenset({'normal'}), children=[option_5]) option_4 = ConvertDynOptionDescription(name='dyn', doc='dyn', properties=frozenset({'normal'}), suffixes=Calculation(func.calc_value, Params((ParamOption(option_3)))), children=[option_5])
option_7 = StrOption(properties=frozenset({'normal'}), name='newvar', doc='No change', multi=False, default=Calculation(func.calc_val, Params((ParamDynOption(option_5, '1', option_4, notraisepropertyerror=False, todict=False)), kwargs={}))) option_7 = StrOption(properties=frozenset({'normal'}), name='newvar', doc='No change', multi=False, default=Calculation(func.calc_val, Params((ParamDynOption(option_5, '1', option_4, notraisepropertyerror=False, todict=False)), kwargs={})))
option_6 = OptionDescription(name='new', doc='new', properties=frozenset({'normal'}), children=[option_7]) option_6 = OptionDescription(name='new', doc='new', properties=frozenset({'normal'}), children=[option_7])
option_1 = OptionDescription(name='rougail', doc='rougail', children=[option_2, option_4, option_6]) option_1 = OptionDescription(name='rougail', doc='rougail', children=[option_2, option_4, option_6])

View file

@ -16,6 +16,6 @@ option_3 = StrOption(properties=frozenset({'mandatory', 'normal'}), name='varnam
option_2 = OptionDescription(name='general', doc='général', properties=frozenset({'normal'}), children=[option_3]) option_2 = OptionDescription(name='general', doc='général', properties=frozenset({'normal'}), children=[option_3])
option_1 = OptionDescription(name='rougail', doc='rougail', children=[option_2]) option_1 = OptionDescription(name='rougail', doc='rougail', children=[option_2])
option_6 = StrOption(properties=frozenset({'normal'}), name='mode', doc='mode', multi=False) option_6 = StrOption(properties=frozenset({'normal'}), name='mode', doc='mode', multi=False)
option_5 = ConvertDynOptionDescription(name='ejabberd', doc='ejabberd', suffixes=Calculation(func.calc_value, Params((ParamOption(option_3)))), properties=frozenset({'normal'}), children=[option_6]) option_5 = ConvertDynOptionDescription(name='ejabberd', doc='ejabberd', properties=frozenset({'normal'}), suffixes=Calculation(func.calc_value, Params((ParamOption(option_3)))), children=[option_6])
option_4 = OptionDescription(name='extra', doc='extra', children=[option_5]) option_4 = OptionDescription(name='extra', doc='extra', children=[option_5])
option_0 = OptionDescription(name='baseoption', doc='baseoption', children=[option_1, option_4]) option_0 = OptionDescription(name='baseoption', doc='baseoption', children=[option_1, option_4])

View file

@ -18,6 +18,6 @@ option_1 = OptionDescription(name='rougail', doc='rougail', children=[option_2])
option_6 = StrOption(properties=frozenset({'mandatory', 'normal'}), name='varname', doc='No change', multi=True, default=['a'], default_multi='a') option_6 = StrOption(properties=frozenset({'mandatory', 'normal'}), name='varname', doc='No change', multi=True, default=['a'], default_multi='a')
option_5 = OptionDescription(name='general', doc='général', properties=frozenset({'normal'}), children=[option_6]) option_5 = OptionDescription(name='general', doc='général', properties=frozenset({'normal'}), children=[option_6])
option_8 = StrOption(properties=frozenset({'normal'}), name='mode', doc='mode', multi=False) option_8 = StrOption(properties=frozenset({'normal'}), name='mode', doc='mode', multi=False)
option_7 = ConvertDynOptionDescription(name='ejabberd', doc='ejabberd', suffixes=Calculation(func.calc_value, Params((ParamOption(option_6)))), properties=frozenset({'normal'}), children=[option_8]) option_7 = ConvertDynOptionDescription(name='ejabberd', doc='ejabberd', properties=frozenset({'normal'}), suffixes=Calculation(func.calc_value, Params((ParamOption(option_6)))), children=[option_8])
option_4 = OptionDescription(name='extra', doc='extra', children=[option_5, option_7]) option_4 = OptionDescription(name='extra', doc='extra', children=[option_5, option_7])
option_0 = OptionDescription(name='baseoption', doc='baseoption', children=[option_1, option_4]) option_0 = OptionDescription(name='baseoption', doc='baseoption', children=[option_1, option_4])