diff --git a/sbin/risotto_auto_doc b/sbin/risotto_auto_doc
index ff7a8d9..ca45548 100755
--- a/sbin/risotto_auto_doc
+++ b/sbin/risotto_auto_doc
@@ -1,14 +1,21 @@
#!/usr/bin/env python3
-from os import listdir
-from os.path import isdir, join
+
+
+from os import listdir, unlink
+from os.path import isdir, isfile, join, abspath
from tabulate import tabulate
from sys import argv
+from yaml import dump
+from ruamel.yaml import YAML
+from glob import glob
from rougail import RougailConfig
from rougail.convert import RougailConvert
from rougail.objspace import RootRougailObject
+from rougail.annotator.family import Mode
from risotto.utils import EXTRA_ANNOTATORS, ROUGAIL_NAMESPACE, ROUGAIL_NAMESPACE_DESCRIPTION
from risotto.image import load_application_service
+from risotto.rougail import func
rougailconfig = RougailConfig
@@ -16,36 +23,146 @@ rougailconfig['variable_namespace'] = ROUGAIL_NAMESPACE
rougailconfig['variable_namespace_description'] = ROUGAIL_NAMESPACE_DESCRIPTION
-DEFAULT_TYPE = 'string'
ROUGAIL_VARIABLE_TYPE = 'https://forge.cloud.silique.fr/risotto/rougail/src/branch/main/doc/variable/README.md#le-type-de-la-variable'
-def add_title_family(elts, dico):
+def add_title_family(elts, dico, modes):
+ is_dynamic = False
for idx, elt in enumerate(elts):
description = elt.doc
if not idx:
description = description.capitalize()
space = idx + 3
- title = '#' * space + f' {description} (*{elt.path}*)'
+ title = '#' * space + f' {description}'
if title not in dico:
- dico[title] = {'variables': [], 'help': '', 'type': ''}
+ if not is_dynamic and hasattr(elt, 'suffixes') and elt.suffixes:
+ is_dynamic = True
+ if is_dynamic:
+ title += '*suffix value*'
+ dico[title] = {'help': '', 'type': 'optiondescription', 'level': idx + 1}
if hasattr(elt, 'information') and hasattr(elt.information, 'help'):
- dico[title]['help'] = elt.information.help
- if hasattr(elt, 'suffixes') and elt.suffixes:
- dico[title]['type'] = 'dynamic'
- dico[title]['suffixes'] = elt.suffixes.path
- if hasattr(elt, 'leadership') and elt.leadership:
- dico[title]['type'] = 'leadership'
- return title
+ help_ = elt.information.help
+ if not help_.endswith('.'):
+ help_ += '.'
+ dico[title]['help'] += help_
+ if hasattr(elt, 'suffixes') and elt.suffixes:
+ dico[title]['suffixes'] = elt.suffixes.path
+ if dico[title]['help']:
+ dico[title]['help'] += ' '
+ dico[title]['help'] += f'This a dynamic family generated from the variable "{elt.suffixes.path}".'
+ if hasattr(elt, 'leadership') and elt.leadership:
+ if dico[title]['help']:
+ dico[title]['help'] += ' '
+ dico[title]['help'] += f'This family is a leadership.'
+ add_mode(elt, dico[title], modes)
+def add_parameter_variable(idx, child, is_leadership, type_, name):
+ if type_ == 'variable':
+ var_path = child.xmlfiles[-1].split('/', 2)[-1]
+ parameter = f'**[{name}]({var_path})**'
+ elif type_ == 'provider':
+ parameter = f'**{name}**'
+ subparameter = ''
+ if hasattr(child, 'properties') and 'mandatory' in child.properties:
+ subparameter = 'mandatory'
+ if ((idx == 0 or not is_leadership) and child.multi is True) or (idx != 0 and is_leadership and child.multi == 'submulti'):
+ if subparameter:
+ subparameter += ', '
+ subparameter += 'multiple'
+ if subparameter:
+ parameter += f'
{subparameter}'
+ var_type = f'**Type:** [`{child.type}`]({ROUGAIL_VARIABLE_TYPE})'
+ return f'{parameter}
{var_type}'
-def parse(applicationservice, elts, dico, providers_suppliers, hidden, objectspace):
+
+def add_title_variable(child, is_leadership, is_dynamic, objectspace):
+ description = f'{child.doc}'
+ if is_dynamic:
+ description += '*suffix value*'
+ if not description.endswith('.'):
+ description += '.'
+ if hasattr(child, 'information') and hasattr(child.information, 'help'):
+ if description:
+ description += '
'
+ help_ = child.information.help
+ if not help_.endswith('.'):
+ help_ += '.'
+ description += help_
+ if hasattr(child, 'default'):
+ default = child.default
+ if isinstance(default, objectspace.value):
+ default = '*calculated*'
+ if isinstance(default, list):
+ default = '
' + ''.join([f'- {val}
' for val in default]) + '
'
+ elif is_leadership and hasattr(child, 'default_multi'):
+ default = child.default_multi
+ else:
+ default = None
+ if hasattr(child, 'choice'):
+ if description:
+ description += '
'
+ description += '**Choices:**'
+ for choice in child.choice:
+ description += f'
- `{choice.name}`'
+ if choice.name == default:
+ description += ' ← default'
+ elif default is not None:
+ if description:
+ description += '
'
+ description += f'**Default:** {default}'
+ if hasattr(child, 'test'):
+ if description:
+ description += '
'
+ description += f'**Example:** {child.test}'
+ return description
+
+
+def add_mode(child, values, modes, parent=None, is_leadership=False):
+ for mode in modes:
+ if mode in child.properties:
+ break
+ else:
+ raise Exception(f'cannot find mode for {child.path}')
+ if is_leadership:
+ for leadership_mode in modes:
+ if leadership_mode in parent.properties:
+ break
+ else:
+ raise Exception(f'cannot find mode for {parent.path}')
+ if modes[mode] < modes[leadership_mode]:
+ mode = leadership_mode
+ values['mode'] = mode
+
+
+def parse(applicationservice,
+ elts,
+ dico,
+ providers_suppliers,
+ hidden,
+ dynamic,
+ objectspace,
+ mandatory_values_without_values,
+ modes,
+ is_dynamic,
+ dynamic_path,
+ is_service,
+ suppliers_variables,
+ ):
elt = elts[-1]
- first_variable = True
if not hidden:
hidden = hasattr(elt, 'properties') and ('hidden' in elt.properties or 'disabled' in elt.properties)
- is_leadership = hasattr(elt, 'leadership') and elt.leadership
+ if not dynamic:
+ dynamic = hasattr(elt, 'suffixes')
+ is_leadership = hasattr(elt, 'leadership') and elt.leadership is True
+ if not is_dynamic:
+ is_dynamic = hasattr(elt, 'suffixes') and elt.suffixes is not None
+ dynamic_path += elt.name
+ if is_dynamic:
+ dynamic_path += "*suffix value*"
+ dynamic_path += '.'
+ leader_is_mandatory = False
+ first_variable = True
for children in vars(elt).values():
if isinstance(children, dict):
children = list(children.values())
@@ -56,60 +173,109 @@ def parse(applicationservice, elts, dico, providers_suppliers, hidden, objectspa
not isinstance(child, RootRougailObject):
continue
if isinstance(child, objectspace.variable):
+ if hasattr(child, 'provider') and child.provider and not child.provider.startswith('global:') and not child.provider.startswith('Host:'):
+ provider_prefix = child.provider
+ if ':' in provider_prefix:
+ provider_prefix = provider_prefix.split(':', 1)[0]
+ if provider_prefix != 'Host':
+ if child.doc == child.name:
+ description = None
+ else:
+ parameter = add_parameter_variable(idx, child, is_leadership, 'provider', child.provider)
+ description = add_title_variable(child, is_leadership, is_dynamic, objectspace)
+ suppliers_variables.setdefault(provider_prefix, {})[child.provider] = {'parameter': parameter, 'description': description}
+ if provider_prefix == child.provider:
+ doc = child.doc
+ if not doc.endswith('.'):
+ doc += '.'
+ suppliers_variables[provider_prefix]['doc'] = doc
if not hidden and (not hasattr(child, 'properties') or ('hidden' not in child.properties and not 'disabled' in child.properties)):
+ if is_service:
+ if hasattr(child, 'provider'):
+ provider = child.provider
+ if ':' not in provider:
+ providers_suppliers['providers'].setdefault(provider, []).append(applicationservice)
+ if hasattr(child, 'supplier') and child.supplier:
+ supplier = child.supplier
+ if ':' not in supplier:
+ providers_suppliers['suppliers'].setdefault(supplier, []).append(applicationservice)
+ if 'mandatory' in child.properties:
+ providers_suppliers['mandatory_suppliers'].setdefault(supplier, []).append(applicationservice)
+ if hasattr(child, 'supplier') and child.supplier and ':' not in child.supplier:
+ raise Exception(f'Main supplier variable "{child.path}" in {child.xmlfiles} must be hidden')
+ if hasattr(child, 'provider') and child.provider and not child.provider.startswith('Host:'):
+ raise Exception(f'Provider variable "{child.path}" in {child.xmlfiles} must be hidden')
if first_variable:
- title = add_title_family(elts, dico)
+ add_title_family(elts, dico, modes)
first_variable = False
- var_title = child.doc
- if hasattr(child, 'properties') and 'mandatory' in child.properties:
- var_title = '**' + var_title + '**'
- var_path = child.xmlfiles[-1].split('/', 2)[-1]
- if child.doc != child.name:
- var_title += f' (*[{child.name}]({var_path})*)'
- else:
- var_title = f'*[{var_title}]({var_path})*'
- if ((idx == 0 or not is_leadership) and child.multi is True) or (idx != 0 and is_leadership and child.multi == 'submulti'):
- var_title += ' [+]'
- values = {'description': var_title,
- }
- if hasattr(child, 'information') and hasattr(child.information, 'help'):
- values['help'] = child.information.help
- if child.type != DEFAULT_TYPE:
- values['type'] = child.type
- if hasattr(child, 'default'):
- default = child.default
- if isinstance(default, objectspace.value):
- default = ''
- if isinstance(default, list):
- default = '
'.join(default)
- values['values'] = default
- if hasattr(child, 'choice'):
- values['choices'] = '
'.join([choice.name for choice in child.choice])
- if hasattr(child, 'provider'):
- provider = child.provider
- values['provider'] = provider
- if ':' not in provider:
- providers_suppliers['providers'].setdefault(provider, []).append(applicationservice)
- if hasattr(child, 'supplier'):
- supplier = child.supplier
- values['supplier'] = supplier
- if ':' not in supplier:
- providers_suppliers['suppliers'].setdefault(supplier, []).append(applicationservice)
- dico[title]['variables'].append(values)
- else:
+ sub_dynamic_path = dynamic_path + child.name
+ if is_dynamic:
+ sub_dynamic_path += "*suffix value*"
+ if not idx and is_leadership and hasattr(child, 'properties') and 'mandatory' in child.properties:
+ leader_is_mandatory = True
+ if hasattr(child, 'properties') and 'mandatory' in child.properties and \
+ mandatory_values_without_values is not None and \
+ not hidden and \
+ not dynamic and \
+ not hasattr(child, 'default') and \
+ not hasattr(child, 'default_multi') and \
+ (not is_leadership or leader_is_mandatory):
+ if not hasattr(child, 'test'):
+ raise Exception(f'{child.path} need test tag to document')
+ value = child.test
+ if ((not is_leadership or not idx) and child.multi is True) or (is_leadership and idx and child.multi == 'submulti'):
+ value = [value]
+ if is_leadership and idx:
+ value = {'0': value}
+ mandatory_values_without_values[child.path] = value
+ parameter = add_parameter_variable(idx, child, is_leadership, 'variable', sub_dynamic_path)
+ #
+ if child.name == child.doc:
+ raise Exception(f'missing doc for variable {child.path} in {child.xmlfiles}')
+ description = add_title_variable(child, is_leadership, is_dynamic, objectspace)
+ values = {'parameter': parameter,
+ 'description': description,
+ 'type': 'option'}
+ if hasattr(child, 'supplier') and child.supplier:
+ values['supplier'] = child.supplier
+ add_mode(child, values, modes, elt, is_leadership)
+ dico[child.path] = values
+ elif is_service:
if hasattr(child, 'provider'):
provider = child.provider
if ':' not in provider:
providers_suppliers['providers'].setdefault(provider, []).append(applicationservice)
- if hasattr(child, 'supplier'):
+ if hasattr(child, 'supplier') and child.supplier:
supplier = child.supplier
if ':' not in supplier:
providers_suppliers['suppliers'].setdefault(supplier, []).append(applicationservice)
+ if 'mandatory' in child.properties:
+ providers_suppliers['mandatory_suppliers'].setdefault(supplier, []).append(applicationservice)
else:
- parse(applicationservice, elts + [child], dico, providers_suppliers, hidden, objectspace)
+ parse(applicationservice,
+ elts + [child],
+ dico,
+ providers_suppliers,
+ hidden,
+ dynamic,
+ objectspace,
+ mandatory_values_without_values,
+ modes,
+ is_dynamic,
+ dynamic_path,
+ is_service,
+ suppliers_variables,
+ )
+ return first_variable
-def build_dependencies_tree(applicationservice, applicationservice_data, applicationservices_data, applicationservices_data_ext, space):
+def build_dependencies_tree(applicationservice,
+ applicationservice_data,
+ applicationservices_data,
+ applicationservices_data_ext,
+ space,
+ only_name: bool=False,
+ ):
depends = []
if applicationservice_data['depends']:
if applicationservice in applicationservices_data:
@@ -132,17 +298,33 @@ def build_dependencies_tree(applicationservice, applicationservice_data, applica
else:
raise Exception(f'cannot find applicationservice "{applicationservice}"')
ext = True
- subdepends = build_dependencies_tree(depend, applicationservice_data, applicationservices_data, applicationservices_data_ext, space + 2)
- if not idx or subdepends:
- title = '\n'
+ subdepends = build_dependencies_tree(depend,
+ applicationservice_data,
+ applicationservices_data,
+ applicationservices_data_ext,
+ space + 2,
+ only_name,
+ )
+ if only_name:
+ if depend not in depends:
+ depends.append(depend)
+ for dep in subdepends:
+ if dep not in depends:
+ depends.append(dep)
else:
- title = ''
- depend_desc = depend
- if ext:
- depend_desc += ' (in external dataset)'
- title = ' ' * space + f'- [{depend_desc}]({url}/{depend}/README.md)'
- depends.append(title)
- depends.extend(subdepends)
+ if not idx or subdepends:
+ title = '\n'
+ else:
+ title = ''
+ depend_desc = depend
+ if ext:
+ depend_desc += ' (in external dataset)'
+ doc = applicationservices_data[depend]["description"]
+ if not doc.endswith('.'):
+ doc += '.'
+ title = ' ' * space + f'- [{depend_desc}]({url}/{depend}/README.md): {doc}'
+ depends.append(title)
+ depends.extend(subdepends)
return depends
@@ -159,9 +341,11 @@ def load_data(url, directory, applicationservices_data, global_data={}):
continue
applicationservices_data[applicationservice] = {'description': applicationservice_data['description'],
'website': applicationservice_data.get('website'),
+ 'help': applicationservice_data.get('help'),
'as_dir': as_dir,
'depends': [],
'used_by': [],
+ 'service': applicationservice_data.get('service', False),
}
if applicationservice in tmps:
for app in tmps.pop(applicationservice):
@@ -182,86 +366,255 @@ def load_data(url, directory, applicationservices_data, global_data={}):
global_data[depend]['used_by'].append(used_by)
-def write_data(applicationservices_data, applicationservices_data_ext):
- dico = {}
- providers_suppliers = {'providers': {}, 'suppliers': {}}
- for applicationservice, applicationservice_data in applicationservices_data.items():
- as_dir = applicationservice_data['as_dir']
+def display_example(as_fh,
+ applicationservice,
+ provider_zone,
+ zones_name,
+ values,
+ ):
+ as_fh.write('\n## Example\n')
+ as_fh.write('\nZone names are provided as examples. Think about adapting with the value of provider_zone in configuration file.\n')
+ as_fh.write('\n```\n')
+ example = {applicationservice: {'applicationservice': applicationservice}}
+ if provider_zone:
+ example[applicationservice]['provider_zone'] = provider_zone
+ if zones_name:
+ example[applicationservice]['zones_name'] = zones_name
+ if values:
+ example[applicationservice]['values'] = values
+# as_fh.write(dump(example, sort_keys=False))
+ yaml = YAML()
+ yaml.indent(sequence=4, offset=2)
+ yaml.dump(example, as_fh)
+ as_fh.write('```\n')
+
+
+def load_dict(applicationservices,
+ applicationservices_data,
+ suppliers_variables,
+ dico,
+ providers_suppliers,
+ mandatory_values_without_values,
+ just_doc=True,
+ ):
+ rougailconfig['dictionaries_dir'] = []
+ extra_dictionaries = {}
+ functions_file = [func.__file__]
+ for applicationservice in applicationservices:
+ as_dir = applicationservices_data[applicationservice]['as_dir']
dirname = join(as_dir, 'dictionaries')
if isdir(dirname):
- rougailconfig['dictionaries_dir'] = [dirname]
- else:
- rougailconfig['dictionaries_dir'] = []
+ rougailconfig['dictionaries_dir'].append(dirname)
dirname_extras = join(as_dir, 'extras')
- extra_dictionaries = {}
if isdir(dirname_extras):
for extra in listdir(dirname_extras):
extra_dir = join(dirname_extras, extra)
if isdir(extra_dir):
extra_dictionaries.setdefault(extra, []).append(extra_dir)
- if not isdir(dirname) and not extra_dictionaries:
- continue
- rougailconfig['extra_dictionaries'] = extra_dictionaries
- converted = RougailConvert(rougailconfig, just_doc=True)
- converted.load_dictionaries()
- converted.annotate()
- objectspace = converted.rougailobjspace
- if hasattr(objectspace.space, 'variables'):
- dico[applicationservice] = {}
- for name, elt in objectspace.space.variables.items():
- parse(applicationservice, [elt], dico[applicationservice], providers_suppliers, False, objectspace)
+ dirname_func = join(as_dir, 'funcs')
+ if isdir(dirname_func):
+ for f in listdir(dirname_func):
+ if f.startswith('__'):
+ continue
+ functions_file.append(abspath(join(dirname_func, f)))
+ rougailconfig['extra_dictionaries'] = extra_dictionaries
+ rougailconfig['functions_file'] = functions_file
+ rougailconfig['extra_annotators'] = EXTRA_ANNOTATORS
+ converted = RougailConvert(rougailconfig, just_doc=just_doc)
+ converted.load_dictionaries()
+ converted.annotate()
+ objectspace = converted.rougailobjspace
+ modes = {name: Mode(idx) for idx, name in enumerate(objectspace.rougailconfig['modes_level'])}
+ if hasattr(objectspace.space, 'variables'):
+ dico[applicationservice] = {}
+ if mandatory_values_without_values is not None:
+ mandatory_values_without_values[applicationservice] = {}
+ mandatory_values = mandatory_values_without_values[applicationservice]
+ else:
+ mandatory_values = None
+ for name, elt in objectspace.space.variables.items():
+ parse(applicationservice,
+ [elt],
+ dico[applicationservice],
+ providers_suppliers,
+ False,
+ False,
+ objectspace,
+ mandatory_values,
+ modes,
+ False,
+ '',
+ applicationservices_data[applicationservice]['service'],
+ suppliers_variables,
+ )
+
+
+def write_data(applicationservices_data, applicationservices_data_ext):
+ dico = {}
+ providers_suppliers = {'providers': {}, 'suppliers': {}, 'mandatory_suppliers': {}, 'depends': {}}
+ mandatory_values_without_values = {}
+ suppliers_variables = {}
+ for applicationservice, applicationservice_data in applicationservices_data.items():
+ if applicationservice_data['service']:
+ depends = build_dependencies_tree(applicationservice,
+ applicationservice_data,
+ applicationservices_data,
+ applicationservices_data_ext,
+ 0,
+ only_name=True,
+ )
+ depends.append(applicationservice)
+ providers_suppliers['depends'][applicationservice] = set(depends)
+ load_dict(['provider-systemd-machined'] + depends,
+ applicationservices_data,
+ suppliers_variables,
+ dico,
+ providers_suppliers,
+ mandatory_values_without_values,
+ just_doc=False,
+ )
+ else:
+ load_dict([applicationservice],
+ applicationservices_data,
+ suppliers_variables,
+ dico,
+ providers_suppliers,
+ None,
+ )
+ for provider in suppliers_variables:
+ for supplier, tdico in suppliers_variables[provider].items():
+ if supplier == 'doc':
+ continue
+ if not tdico['description']:
+ raise Exception(f'variable with provider "{supplier}" must have a description')
+ #
+ for filename in glob('seed/README.*.md'):
+ unlink(filename)
+ for provider in suppliers_variables:
+ with open(join(f'seed/README.{provider}.md'), 'w') as as_fh:
+ as_fh.write(f'---\ngitea: none\ninclude_toc: true\n---\n\n')
+ as_fh.write(f'\n[Return to the list of application services.](README.md)\n')
+ as_fh.write(f'# {provider}\n\n')
+ as_fh.write(f'## Synopsis\n\n')
+ as_fh.write(suppliers_variables[provider][provider]['description'])
+ as_fh.write(f'\n\n## Variables\n\n')
+ providers = []
+ for provider_name, tdico in suppliers_variables[provider].items():
+ if ':' in provider_name:
+ providers.append(list(tdico.values()))
+ if providers:
+ as_fh.write(tabulate(providers, headers=['Parameter', 'Comment'], tablefmt="github"))
+ as_fh.write(f'\n')
+ applicationservices = providers_suppliers['providers'].get(provider, [])
+ if applicationservices:
+ if len(applicationservices) == 1:
+ as_fh.write(f'\n## Provider\n\n')
+ for applicationservice in applicationservices:
+ doc = applicationservices_data[applicationservice]["description"]
+ if not doc.endswith('.'):
+ doc += '.'
+ as_fh.write(f'[{applicationservice}]({applicationservice}/README.md): {doc}\n')
+ else:
+ as_fh.write(f'\n## Providers\n\n')
+ for applicationservice in applicationservices:
+ doc = applicationservices_data[applicationservice]["description"]
+ if not doc.endswith('.'):
+ doc += '.'
+ as_fh.write(f'- [{applicationservice}]({applicationservice}/README.md): {doc}\n')
+ applicationservices = providers_suppliers['suppliers'].get(provider, [])
+ if applicationservices:
+ if len(applicationservices) == 1:
+ as_fh.write(f'\n## Supplier\n\n')
+ for applicationservice in applicationservices:
+ doc = applicationservices_data[applicationservice]["description"]
+ if not doc.endswith('.'):
+ doc += '.'
+ as_fh.write(f'[{applicationservice}]({applicationservice}/README.md): {doc}\n')
+ else:
+ as_fh.write(f'\n## Suppliers\n\n')
+ for applicationservice in applicationservices:
+ doc = applicationservices_data[applicationservice]["description"]
+ if not doc.endswith('.'):
+ doc += '.'
+ as_fh.write(f'- [{applicationservice}]({applicationservice}/README.md): {doc}\n')
+ #
for applicationservice, applicationservice_data in applicationservices_data.items():
as_dir = applicationservice_data['as_dir']
+ local_dico = dico
with open(join(as_dir, 'README.md'), 'w') as as_fh:
as_fh.write(f'---\ngitea: none\ninclude_toc: true\n---\n\n')
+ as_fh.write(f'\n[Return to the list of application services.](../README.md)\n')
as_fh.write(f'# {applicationservice}\n\n')
- as_fh.write(f'## Description\n\n')
- description = applicationservice_data['description'] + '.\n'
+ as_fh.write(f'## Synopsis\n\n')
+ description = applicationservice_data['description'] + '.'
if applicationservice_data['website']:
- description += f'\n[For more informations]({applicationservice_data["website"]})\n'
+ description = f"\n[{description}]({applicationservice_data['website']})"
+ description += '\n'
+ if applicationservice_data['help']:
+ help_ = applicationservice_data['help'].strip()
+ if not help_.endswith('.'):
+ help_ += 'p.'
+ description += f'\n{help_}\n'
as_fh.write(description)
+ # variables
+ if applicationservice in local_dico and local_dico[applicationservice]:
+ display_variables(as_dir, as_fh, applicationservice, local_dico)
+ if applicationservice_data['service']:
+ mandatory_zones_name = {}
+ zones_name = {}
+ provider_name = None
+ if applicationservice_data['depends']:
+ depends_set = providers_suppliers['depends'][applicationservice]
+ # providers
+ for provider, provider_as in providers_suppliers['providers'].items():
+ if not set(provider_as) & depends_set:
+ continue
+ provider_name = provider.lower()
+ break
+ #
+ if providers_suppliers['suppliers'] and list(providers_suppliers['suppliers']) != ['Host']:
+ as_fh.write('\n## Requirements services\n')
+ provider_hosts = []
+ for provider, provider_data in providers_suppliers['suppliers'].items():
+ if provider == 'Host':
+ continue
+ if applicationservice not in provider_data:
+ continue
+ suppliers = providers_suppliers['providers'].get(provider, [])
+ if len(suppliers) == 1:
+ if suppliers[0] in provider_hosts:
+ continue
+ provider_hosts.append(suppliers[0])
+ filename = f'README.{provider}.md'
+ if isfile(join('seed', filename)):
+ msg = f'[{provider}](../{filename})'
+ else:
+ msg = provider
+ if provider in providers_suppliers['mandatory_suppliers']:
+ mandatory_zones_name[provider] = msg
+ else:
+ zones_name[provider] = msg
+ if mandatory_zones_name:
+ as_fh.write('\n### Mandatories\n\n')
+ for provider, msg in mandatory_zones_name.items():
+ as_fh.write(f'- {msg}: {suppliers_variables[provider]["doc"]}\n')
+ if zones_name:
+ as_fh.write('\n### Optionals\n\n')
+ for provider, msg in zones_name.items():
+ as_fh.write(f'- {msg}: {suppliers_variables[provider]["doc"]}\n')
+ #
+ mandatory_zones_name = [provider.lower() for provider in mandatory_zones_name]
+ mandatory_zones_name.sort()
+ display_example(as_fh,
+ applicationservice,
+ provider_name,
+ mandatory_zones_name,
+ mandatory_values_without_values[applicationservice],
+ )
if applicationservice_data['depends']:
- as_fh.write(f'\n## Dependances\n\n')
+ as_fh.write('\n## Dependances\n\n')
for depend in build_dependencies_tree(applicationservice, applicationservice_data, applicationservices_data, applicationservices_data_ext, 0):
as_fh.write(f'{depend}\n')
- if applicationservice in dico and dico[applicationservice]:
- as_fh.write('\n## Variables\n\n')
- for title, data in dico[applicationservice].items():
- as_fh.write(f'{title}\n')
- if data['type'] == 'leadership':
- as_fh.write('\nThis a family is a leadership.\n')
- if data['type'] == 'dynamic':
- as_fh.write(f'\nThis a dynamic family generated from the variable "{data["suffixes"]}".\n')
- if data['help']:
- as_fh.write(f'\n{data["help"]}\n')
- keys = []
- if data['variables']:
- variables = data['variables']
- for variable in variables:
- for key in variable:
- if key not in keys:
- keys.append(key)
- values = []
- for variable in variables:
- value = []
- for key in keys:
- if key in variable:
- val = variable[key]
- elif key == 'type':
- val = DEFAULT_TYPE
- else:
- val = ''
- if key == 'type':
- val = f'[{val}]({ROUGAIL_VARIABLE_TYPE})'
- value.append(val)
- values.append(value)
- as_fh.write('\n')
- as_fh.write(tabulate(values, headers=[key.capitalize() for key in keys], tablefmt="github"))
- as_fh.write('\n')
- as_fh.write('\n')
- # FIXME if not applicationservice_data['used_by']:
- # FIXME as_fh.write('\n## Variables with dependencies\n\n')
- as_fh.write('\n- [+]: variable is multiple\n- **bold**: variable is mandatory\n')
if applicationservice_data['used_by']:
as_fh.write('\n## Used by\n\n')
if len(applicationservice_data['used_by']) == 1:
@@ -274,79 +627,120 @@ def write_data(applicationservices_data, applicationservices_data_ext):
for provider, provider_as in providers_suppliers['providers'].items():
if not applicationservice in provider_as:
continue
- for supplier in providers_suppliers['suppliers'][provider]:
- if supplier in linked:
- continue
- linked.append(supplier)
+ if provider in providers_suppliers['suppliers']:
+ for supplier in providers_suppliers['suppliers'][provider]:
+ if supplier in linked:
+ continue
+ linked.append(supplier)
linked.sort()
if linked:
if len(linked) == 1:
- as_fh.write('\n## Supplier\n\n')
- as_fh.write(f'[{linked[0]}](../{linked[0]}/README.md)\n')
+ as_fh.write('\n## Useful for service\n\n')
+ description = applicationservices_data[linked[0]]["description"]
+ if not description.endswith('.'):
+ description += '.'
+ as_fh.write(f'[{linked[0]}](../{linked[0]}/README.md): {description}\n')
else:
- as_fh.write('\n## Suppliers\n\n')
+ as_fh.write('\n## Useful for services\n\n')
for supplier in linked:
- as_fh.write(f'- [{supplier}](../{supplier}/README.md)\n')
- linked = []
- for supplier, supplier_as in providers_suppliers['suppliers'].items():
- if not applicationservice in supplier_as:
- continue
- for provider in providers_suppliers['providers'][supplier]:
- if provider in linked:
- continue
- linked.append(provider)
- linked.sort()
- if linked:
- if len(linked) == 1:
- as_fh.write('\n## Provider\n\n')
- as_fh.write(f'[{linked[0]}](../{linked[0]}/README.md)\n')
- else:
- as_fh.write('\n## Providers\n\n')
- for provider in linked:
- as_fh.write(f'- [{provider}](../{provider}/README.md)\n')
- as_fh.write(f'\n[All applications services for this dataset.](../README.md)\n')
+ description = applicationservices_data[supplier]["description"]
+ if not description.endswith('.'):
+ description += '.'
+ as_fh.write(f'- [{supplier}](../{supplier}/README.md): {description}\n')
with open('seed/README.md', 'w') as as_fh:
- as_fh.write('# Application services\n\n')
- applicationservices = {}
- for applicationservice in applicationservices_data:
- applicationservices.setdefault(applicationservice.split('-')[0], []).append(applicationservice)
- applicationservice_categories = list(applicationservices.keys())
- applicationservice_categories.sort()
- for category in applicationservice_categories:
- applicationservices_ = applicationservices[category]
- if len(applicationservices_) == 1:
- applicationservice = applicationservices_[0]
- applicationservice_data = applicationservices_data[applicationservice]
- as_fh.write(f'- [{applicationservice}]({applicationservice}/README.md): {applicationservice_data["description"]}\n')
+ for service in [True, False]:
+ if service:
+ as_fh.write('# Application services\n\n')
else:
- as_fh.write(f'- {category}:\n')
- applicationservices_.sort()
- for applicationservice in applicationservices_:
+ as_fh.write('# Application dependencies\n\n')
+ applicationservices = {}
+ for applicationservice, applicationservice_data in applicationservices_data.items():
+ if applicationservice_data['service'] is not service:
+ continue
+ applicationservices.setdefault(applicationservice.split('-')[0], []).append(applicationservice)
+ applicationservice_categories = list(applicationservices.keys())
+ applicationservice_categories.sort()
+ for category in applicationservice_categories:
+ applicationservices_ = applicationservices[category]
+ if len(applicationservices_) == 1:
+ applicationservice = applicationservices_[0]
applicationservice_data = applicationservices_data[applicationservice]
- as_fh.write(f' - [{applicationservice}]({applicationservice}/README.md): {applicationservice_data["description"]}\n')
+ as_fh.write(f'- [{applicationservice}]({applicationservice}/README.md): {applicationservice_data["description"]}\n')
+ else:
+ as_fh.write(f'- {category}:\n')
+ applicationservices_.sort()
+ for applicationservice in applicationservices_:
+ applicationservice_data = applicationservices_data[applicationservice]
+ as_fh.write(f' - [{applicationservice}]({applicationservice}/README.md): {applicationservice_data["description"]}\n')
providers = list(providers_suppliers['providers'].keys())
providers.sort()
if providers:
- as_fh.write('\n# Providers and suppliers\n\n')
+ as_fh.write('\n# Providers\n\n')
for provider in providers:
- as_fh.write(f'- {provider}:\n')
- if providers_suppliers['providers'][provider]:
- if len(providers_suppliers['providers'][provider]) == 1:
- applicationservice = providers_suppliers['providers'][provider][0]
- as_fh.write(f' - Provider: [{applicationservice}]({applicationservice}/README.md)\n')
- else:
- as_fh.write(f' - Providers:\n')
- for applicationservice in providers_suppliers['providers'][provider]:
- as_fh.write(f' - [{applicationservice}]({applicationservice}/README.md)\n')
- if providers_suppliers['suppliers']:
- if len(providers_suppliers['suppliers'][provider]) == 1:
- applicationservice = providers_suppliers['suppliers'][provider][0]
- as_fh.write(f' - Supplier: [{applicationservice}]({applicationservice}/README.md)\n')
- else:
- as_fh.write(f' - Suppliers:\n')
- for applicationservice in providers_suppliers['suppliers'][provider]:
- as_fh.write(f' - [{applicationservice}]({applicationservice}/README.md)\n')
+ if provider in suppliers_variables[provider]:
+ as_fh.write(f'- [{provider}](README.{provider}.md): {suppliers_variables[provider]["doc"]}\n')
+
+
+def display_variables(as_dir, as_fh, applicationservice, local_dico):
+ for main_title, modes in [('Basic variables', ['basic']),
+ ('Variables', ['basic', 'normal']),
+ ('Variables for expert', ['basic', 'normal', 'expert']),
+ ]:
+ main_title_added = False
+ titles = []
+ variables = []
+ parent_path = None
+ for title, data in list(local_dico[applicationservice].items()):
+ keys = []
+ if data['type'] == 'optiondescription':
+ #if data['mode'] not in modes:
+ # continue
+ if variables:
+ as_fh.write(tabulate(variables, headers=['Parameter', 'Comment'], tablefmt="github"))
+ as_fh.write('\n')
+ as_fh.write('\n')
+ variables = []
+ parent_path = None
+ title_level = data['level']
+ len_titles = len(titles)
+ if len_titles < title_level:
+ titles.append((None, None))
+ titles[title_level - 1] = (title, data)
+ if len_titles > title_level:
+ for idx in range(title_level, len_titles):
+ titles.pop(title_level)
+ else:
+ if data['mode'] not in modes:
+ continue
+ if not main_title_added:
+ as_fh.write(f'\n## {main_title}\n\n')
+ main_title_added = True
+ for idx, td in enumerate(titles):
+ t, d = td
+ if not t:
+ continue
+ as_fh.write(f'{t}\n\n')
+ if d['help']:
+ help = d['help']
+ if not help.endswith('.'):
+ help += '.'
+ as_fh.write(f'{help}\n\n')
+ titles[idx] = (None, None)
+ if data['mode'] != modes[-1]:
+ continue
+ new_parent_path = title.rsplit('.', 1)[0]
+ if variables and parent_path != new_parent_path:
+ as_fh.write(tabulate(variables, headers=['Parameter', 'Comments'], tablefmt="github"))
+ as_fh.write('\n')
+ as_fh.write('\n')
+ variables = []
+ parent_path = new_parent_path
+ variables.append([data['parameter'], data['description']])
+ del local_dico[applicationservice][title]
+ if variables:
+ as_fh.write(tabulate(variables, headers=['Parameter', 'Comments'], tablefmt="github"))
+ as_fh.write('\n')
def main():
diff --git a/src/risotto/utils.py b/src/risotto/utils.py
index 1372e8a..c72bbc2 100644
--- a/src/risotto/utils.py
+++ b/src/risotto/utils.py
@@ -11,7 +11,7 @@ from pprint import pprint
MULTI_FUNCTIONS = []
EXTRA_ANNOTATORS = ['risotto.rougail']
ROUGAIL_NAMESPACE = 'general'
-ROUGAIL_NAMESPACE_DESCRIPTION = 'Général'
+ROUGAIL_NAMESPACE_DESCRIPTION = 'General'
HERE = environ['PWD']
IP_DIR = join(HERE, 'ip')