Compare commits

..

No commits in common. "0.1.0a16" and "main" have entirely different histories.

315 changed files with 487 additions and 2634 deletions

View file

@ -1,122 +0,0 @@
## 0.1.0a16 (2025-09-29)
### Feat
- variable with an index is an integer variable
- default value for a calculated variable with an unknown optional variable
- **#26**: convert cidr and network_cidr format
- add integer type which will replace number type
## 0.1.0a15 (2025-09-22)
### Fix
- dictionary => structure
## 0.1.0a14 (2025-06-18)
### Fix
- rougail separation
## 0.1.0a13 (2025-05-15)
### Fix
- no multi empty line when a variable finish by a multi line description
## 0.1.0a12 (2025-05-12)
### Fix
- black
## 0.1.0a11 (2025-05-09)
### Fix
- format with default_dictionary_format_version configuration
## 0.1.0a10 (2025-05-02)
### Fix
- do not load use_data with rougail cli
- support {{ suffix }} name in 1.1 format version
## 0.1.0a9 (2025-04-30)
### Feat
- add yamllint validation
### Fix
- update tests
- add version
## 0.1.0a8 (2025-04-01)
### Fix
- update tests
## 0.1.0a7 (2025-03-30)
### Feat
- support multi lines for help
## 0.1.0a6 (2025-03-28)
### Fix
- do not add multi \n at ends of export
## 0.1.0a5 (2025-03-27)
### Fix
- if and for in 3 lines
## 0.1.0a4 (2025-03-27)
### Feat
- format jinja template
## 0.1.0a3 (2025-03-27)
### Feat
- add secret_manager support
- add Namespace(Param|Calculation) support
### Fix
- do not add namespace in param
- an empty variable is []
## 0.1.0a2 (2025-03-26)
### Fix
- pyproject.toml
## 0.1.0a1 (2025-03-26)
### Fix
- add pyproject.toml
## 0.1.0a0 (2025-02-10)
### Feat
- output return status too
## 0.0.1a0 (2025-01-04)
### Fix
- remove prefix_path

View file

@ -1,47 +0,0 @@
[build-system]
build-backend = "flit_core.buildapi"
requires = ["flit_core >=3.8.0,<4"]
[project]
name = "rougail.output_formatter"
version = "0.1.0a16"
authors = [{name = "Emmanuel Garette", email = "gnunux@gnunux.info"}]
readme = "README.md"
description = "Rougail output formatter"
requires-python = ">=3.8"
license = {file = "LICENSE"}
classifiers = [
"License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)",
"Programming Language :: Python",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: 3.14",
"Programming Language :: Python :: 3",
"Operating System :: OS Independent",
"Natural Language :: English",
"Natural Language :: French",
]
dependencies = [
"rougail >= 1.1,<2",
"djlint == 1.36.4",
]
[project.urls]
Home = "https://forge.cloud.silique.fr/stove/rougail-output-formatter"
[tool.commitizen]
name = "cz_conventional_commits"
tag_format = "$version"
version_scheme = "pep440"
version_provider = "pep621"
version_files = [
"src/rougail/output_formatter/__version__.py",
"pyproject.toml:version"
]
update_changelog_on_bump = true
changelog_merge_prerelease = true

View file

@ -1,6 +1,6 @@
"""
Silique (https://www.silique.fr)
Copyright (C) 2024-2025
Copyright (C) 2024
This program is free software: you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by the
@ -16,72 +16,33 @@ You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from io import BytesIO
from pathlib import Path
from typing import Optional
from ruamel.yaml import YAML, CommentedMap
from ruamel.yaml.representer import RoundTripRepresenter
from ruamel.yaml.tokens import CommentToken
from ruamel.yaml.error import CommentMark
from ruamel.yaml.comments import CommentedSeq
from ruamel.yaml.scalarstring import (
LiteralScalarString,
FoldedScalarString,
ScalarString,
)
from djlint.settings import Config
from djlint.reformat import formatter
from ruamel.yaml.scalarstring import LiteralScalarString, FoldedScalarString
from tiramisu import undefined
from tiramisu.config import get_common_path
from rougail.convert import RougailConvert
from rougail.convert.object_model import (
Variable,
Family,
Calculation,
JinjaCalculation,
IdentifierCalculation,
IdentifierPropertyCalculation,
NamespaceCalculation,
IdentifierParam,
IndexCalculation,
VariableCalculation,
IndexParam,
NamespaceParam,
Param,
AnyParam,
)
from rougail.tiramisu import normalize_family, RENAME_TYPE
from rougail.utils import undefined
from rougail.object_model import Variable, Family, Calculation, JinjaCalculation, IdentifierCalculation, IdentifierPropertyCalculation, IdentifierParam, IndexCalculation, IndexParam, Param
from rougail.utils import normalize_family
from .upgrade import RougailUpgrade
from .__version__ import __version__
def _(text):
return text
# XXX explicit null
def represent_none(self, data):
return self.represent_scalar("tag:yaml.org,2002:null", "null")
def represent_str(self, data):
if data == "":
return self.represent_scalar("tag:yaml.org,2002:null", "")
return self.represent_scalar("tag:yaml.org,2002:str", data)
RoundTripRepresenter.add_representer(type(None), represent_none)
RoundTripRepresenter.add_representer(str, represent_str)
# XXX
class RougailOutputFormatter:
output_name = "formatter"
output_name = 'formatter'
def __init__(
self,
@ -93,76 +54,27 @@ class RougailOutputFormatter:
) -> None:
self.basic_types = {
str: "string",
int: "integer",
int: "number",
bool: "boolean",
float: "float",
}
if rougailconfig is None:
from rougail import RougailConfig
rougailconfig = RougailConfig
rougailconfig["step.output"] = self.output_name
self.rougailconfig = rougailconfig
if self.rougailconfig["step.output"] != self.output_name:
raise ExtentionError(
_('the "step.output" is not set to "{0}"').format(self.output_name)
)
if rougailconfig["step.output"] != self.output_name:
raise ExtentionError(_('the "step.output" is not set to "{0}"').format(self.output_name))
# yaml.top_level_colon_align = True
self.main_namespace = normalize_family(self.rougailconfig["main_namespace"])
self.has_default_structural_format_version = (
self.rougailconfig["default_structural_format_version"] is not None
)
self.config = Config()
self.config.profile = "jinja"
self.config.line_break_after_multiline_tag = True
self.config.indent = " "
self.attributes = {}
self.yaml = YAML()
def run(self):
self.upgrade()
self.families = {self.main_namespace: CommentedMap()}
self.parse()
self.yaml.indent(mapping=2, sequence=4, offset=2)
self.yaml.version = "1.2"
self.yaml.explicit_start = True
self.yaml.explicit_end = True
self.default_flow_style = False
with BytesIO() as ymlfh:
families = self.families[self.main_namespace]
if not families:
self.yaml.dump("", ymlfh)
else:
self.yaml.dump(families, ymlfh)
ret = ymlfh.getvalue().decode("utf-8").strip()
return True, ret
def get_attributes(self, obj, excludes=[]) -> dict:
type_name = obj.__name__
if type_name == "Variable" and excludes == []:
raise Exception("pff")
if type_name not in self.attributes:
self.attributes[type_name] = {
str(attr): o.default
for attr, o in obj.model_fields.items()
if str(attr) not in excludes
}
return self.attributes[type_name]
def upgrade(self) -> None:
filenames = self.rougailconfig["main_structural_directories"]
if len(filenames) > 1:
raise Exception(_("only one file is allowed"))
self.main_namespace = rougailconfig["main_namespace"]
filenames = rougailconfig["main_dictionaries"]
if len(rougailconfig["main_dictionaries"]) > 1:
raise Exception(_('only one file is allowed'))
filename = Path(filenames[0])
if not filename.is_file():
raise Exception(_("only a file is allowed"))
self.version_name, self.original_yaml = RougailUpgrade(self.rougailconfig).run(
filename
)
self.version_name, datas = RougailUpgrade(self.rougailconfig).run(filename)
self.rougail = RougailConvert(self.rougailconfig)
raise Exception(_('only a file is allowed'))
self.original_yaml = RougailUpgrade(rougailconfig).run(filename)
datas = RougailUpgrade(rougailconfig).run(filename)
self.rougail = RougailConvert(rougailconfig)
self.rougail.load_config()
self.rougail.init()
self.filename_str = str(filename)
@ -181,35 +93,54 @@ class RougailOutputFormatter:
"1.1",
datas,
)
self.yaml = YAML()
def print(self):
ret, data = self.run()
print(data)
def run(self):
self.families_attributes = {attr: obj.get("default") for attr, obj in self.rougail.family.model_json_schema()["properties"].items()}
self.dynamics_attributes = {attr: obj.get("default") for attr, obj in self.rougail.dynamic.model_json_schema()["properties"].items()}
self.variables_attributes = {attr: obj.get("default") for attr, obj in self.rougail.variable.model_json_schema()["properties"].items()}
self.families = {None: CommentedMap()}
self.parse()
self.yaml.indent(mapping=2, sequence=4, offset=2)
self.yaml.explicit_start=True
self.default_flow_style = False
with BytesIO() as ymlfh:
self.yaml.dump(self.families[None], ymlfh)
ret = ymlfh.getvalue().decode("utf-8").strip() + '\n'
return ret
def print(self):
print(self.run())
def parse(self):
self.families[self.main_namespace][self.version_name] = float(
self.rougail.version
)
self.remaining = len(self.rougail.paths._data)
# FIXME path to relative !
if self.rougail.namespace:
version_path = f'{self.rougail.namespace}.version'
else:
version_path = 'version'
if version_path in self.rougail.paths._data:
version_name = '_version'
else:
version_name = 'version'
self.families[None][version_name] = None
self.families[None].yaml_value_comment_extend(version_name, [CommentToken('\n\n', CommentMark(0)), None])
version = None
for path, obj in self.rougail.paths._data.items():
self.remaining -= 1
if version is None or version == '':
version = obj.version
if path == self.rougail.namespace:
# self.families[path] = self.families[None]
self.families[path] = self.families[None]
continue
if isinstance(obj, Family):
self.parse_family(path, obj)
elif isinstance(obj, Variable):
if isinstance(obj, Variable):
self.parse_variable(path, obj)
if list(self.families[self.main_namespace]) != [self.version_name]:
self.families[self.main_namespace].yaml_value_comment_extend(
self.version_name, [CommentToken("\n\n", CommentMark(0)), None]
)
if self.has_default_structural_format_version:
del self.families[self.main_namespace][self.version_name]
if not version:
raise Exception(_(f'no variables in file {self.filename_str}'))
self.families[None][version_name] = float(version)
def parse_family(self, path, obj):
children = [p.rsplit(".", 1)[-1] for p in self.rougail.parents[path]]
children = [p.rsplit('.', 1)[-1] for p in self.rougail.parents[path]]
parent, name = self.get_parent_name(path)
ret = self.families[parent]
family = CommentedMap()
@ -224,11 +155,11 @@ class RougailOutputFormatter:
force_keys = list(yaml_data)
type_ = obj.type
if type_ == "dynamic":
attributes = self.get_attributes(self.rougail.dynamic)
attributes = self.dynamics_attributes
else:
attributes = self.get_attributes(self.rougail.family)
attributes = self.families_attributes
for attr, default_value in attributes.items():
if attr in ["name", "path", "namespace", "version", "xmlfiles"]:
if attr in ["name", "path", "namespace", "version", "path_prefix", "xmlfiles"]:
continue
try:
value = getattr(obj, attr)
@ -237,31 +168,21 @@ class RougailOutputFormatter:
if attr != "type" and attr not in force_keys and value == default_value:
continue
if attr in children:
attr = f"_{attr}"
family[attr] = self.object_to_yaml(attr, type_, value, False, path)
if type_ == "dynamic" or (children and type_ == "family"):
attr = f'_{attr}'
value = self.object_to_yaml(attr, type_, value, False, path)
family[attr] = value
if type_ == "dynamic" or (children and type_ == 'family'):
if "_type" in family:
del family["_type"]
else:
del family["type"]
if not set(family):
ret[name] = CommentedMap()
ret.yaml_value_comment_extend(
name, [CommentToken("\n\n", CommentMark(0)), None]
)
elif not set(family) - {"description"}:
ret.yaml_value_comment_extend(name, [CommentToken('\n\n', CommentMark(0)), None])
elif not set(family) - {'description'}:
#
ret[name] = CommentedMap()
add_column = 3
path_len = path.count(".")
if self.rougail.namespace:
path_len -= 1
column = path_len * 2 + len(name) + add_column
if self.remaining:
description = family["description"].strip() + "\n\n"
else:
description = family["description"].strip()
ret.yaml_add_eol_comment(description, name, column=column)
ret.yaml_add_eol_comment(family["description"] + '\n\n', name)
else:
self.add_space(family)
ret[name] = family
@ -282,33 +203,9 @@ class RougailOutputFormatter:
force_keys = list(yaml_data)
multi = obj.multi or isinstance(obj.default, list)
type_ = obj.type
if type_ in RENAME_TYPE:
type_ = RENAME_TYPE[type_]
if type_ == 'cidr' or type_ == 'network_cidr':
if type_ == 'cidr':
type_ = 'ip'
else:
type_ = 'network'
if not obj.params:
obj.params = []
key = 'cidr'
param = AnyParam(
key='cidr',
value=True,
type="any",
path=None,
attribute=None,
family_is_dynamic=None,
namespace=self.rougail.namespace,
xmlfiles=obj.xmlfiles,
)
obj.params.append(param)
for attr, default_value in self.get_attributes(
self.rougail.variable, ["name", "path", "namespace", "version", "xmlfiles"]
).items():
if attr == "type":
value = type_
else:
for attr, default_value in self.variables_attributes.items():
if attr in ["name", "path", "namespace", "version", "path_prefix", "xmlfiles"]:
continue
try:
value = getattr(obj, attr)
except AttributeError:
@ -317,96 +214,50 @@ class RougailOutputFormatter:
continue
value = self.object_to_yaml(attr, type_, value, multi, path)
variable[attr] = value
if variable.get("mandatory") is True and None not in variable.get(
"choices", []
):
if variable.get("mandatory") is True and None not in variable.get("choices", []):
del variable["mandatory"]
if "default" in variable:
if isinstance(obj.default, VariableCalculation):
is_multi = "multi" in variable and variable["multi"] is True
if "type" in variable or is_multi:
other_path = self.rougail.paths.get_full_path(obj.default.variable, path)
if other_path in self.rougail.paths:
other_obj = self.rougail.paths[other_path]
if "type" in variable and variable["type"] == other_obj.type:
del variable["type"]
if is_multi and obj.multi:
del variable["multi"]
if "type" in variable and isinstance(obj.default, IndexCalculation) and variable["type"] == "integer":
del variable["type"]
if "type" in variable and variable["type"] in [
"string",
"boolean",
"integer",
"float",
]:
if "type" in variable and variable["type"] in ["string", "boolean", "number", "float"]:
if variable["default"] and isinstance(variable["default"], list):
tested_value = variable["default"][0]
else:
tested_value = variable["default"]
if variable["type"] == self.basic_types.get(type(tested_value), None):
del variable["type"]
if (
"multi" in variable
and variable["multi"] is True
and isinstance(variable["default"], list)
):
if "multi" in variable and variable["multi"] is True and isinstance(variable["default"], list):
del variable["multi"]
elif variable.get("type") == "choice" and "choices" in variable:
del variable["type"]
elif variable.get("type") == "string":
# default type is string
del variable["type"]
if set(variable) in [{"multi"}, {"multi", "description"}]:
if set(variable) in [{"multi"}, {'multi', 'description'}]:
variable["default"] = []
variable.pop("multi")
elif variable.get("type") == "boolean" and not multi:
# if boolean, the default value is True
del variable["type"]
variable["default"] = True
if (
"default" not in variable
and variable.get("multi") is True
and not set(variable) - {"default", "description", "multi"}
):
variable["default"] = []
del variable["multi"]
if not isinstance(variable.get("default"), dict) and not set(variable) - {
"default",
"description",
}:
if not isinstance(variable.get("default"), dict) and not set(variable) - {'default', 'description'}:
# shorthand notation
default = variable.get("default")
default = variable.get('default')
ret[name] = default
add_column = 3
if isinstance(default, list):
ret[name] = CommentedSeq()
if not default:
add_column += 3
for d in default:
ret[name].append(d)
else:
if default is None:
ret[name] = ""
else:
ret[name] = default
add_column += len(str(default)) + 1
if "description" in variable:
description = variable["description"].strip()
if self.remaining and (not multi or not default):
description = variable["description"]
if not multi or not default:
description += "\n\n"
path_len = path.count(".")
if self.rougail.namespace:
path_len -= 1
column = path_len * 2 + len(name) + add_column
ret.yaml_add_eol_comment(description, name, column=column)
ret.yaml_add_eol_comment(description, name)
if multi and default:
self.add_space(ret)
else:
self.add_space(ret)
else:
if "default" in variable and variable["default"] is None:
variable["default"] = ""
ret[name] = variable
self.add_space(variable)
@ -414,141 +265,85 @@ class RougailOutputFormatter:
def _get_last_obj(o, parent, param, typ):
if isinstance(o, CommentedMap):
param = list(o)[-1]
return _get_last_obj(o[param], o, param, "map")
return _get_last_obj(o[param], o, param, 'map')
if isinstance(o, CommentedSeq):
param = len(o) - 1
return _get_last_obj(o[param], o, param, "seq")
return _get_last_obj(o[param], o, param, 'seq')
return typ, parent, param
param = list(obj)[-1]
typ, parent, param = _get_last_obj(obj[param], obj, param, "map")
if isinstance(parent[param], ScalarString):
enter = "\n"
else:
enter = "\n\n"
if typ == "seq":
typ, parent, param = _get_last_obj(obj[param], obj, param, 'map')
if typ == 'seq':
func = parent.yaml_key_comment_extend
else:
func = parent.yaml_value_comment_extend
if self.remaining:
func(param, [CommentToken(enter, CommentMark(0)), None])
func(param, [CommentToken('\n\n', CommentMark(0)), None])
def object_to_yaml(self, key, type_, value, multi, object_path):
if isinstance(value, list):
if key == "params":
if key == 'params':
new_values = CommentedMap()
else:
new_values = CommentedSeq()
for v in value:
new_value = self.object_to_yaml(key, type_, v, multi, object_path)
if key == "params":
if "min_number" in new_value:
new_value["min_integer"] = new_value.pop("min_number")
if "max_number" in new_value:
new_value["max_integer"] = new_value.pop("max_number")
if key == 'params':
new_values.update(new_value)
else:
new_values.append(new_value)
return new_values
if isinstance(value, JinjaCalculation):
jinja = CommentedMap()
jinja_values = formatter(self.config, value.jinja.strip())[:-1]
if key == "default" and not multi:
jinja["jinja"] = FoldedScalarString(jinja_values)
fold_pos = []
old_i = 0
for i, ltr in enumerate(jinja_values):
if ltr == "\n":
fold_pos.append(i - old_i)
old_i = 1
jinja["jinja"].fold_pos = fold_pos
elif key == "secret_manager":
return self.object_to_yaml(
"params", type_, value.params, multi, object_path
)
# replace \n to space a add index of \n (now a space) to fold_pos
jinja_values = value.jinja.strip()
if key == 'default' and not multi:
jinja["jinja"] = FoldedScalarString(jinja_values.replace('\n', ' '))
jinja["jinja"].fold_pos = [i for i, ltr in enumerate(jinja_values) if ltr == '\n']
else:
jinja["jinja"] = LiteralScalarString(jinja_values)
if value.return_type:
return_type = value.return_type
if return_type in RENAME_TYPE:
return_type = RENAME_TYPE[return_type]
jinja["return_type"] = return_type
jinja["return_type"] = value.return_type
if value.description:
if "\n" in value.description:
jinja["description"] = LiteralScalarString(value.description.strip())
else:
jinja["description"] = value.description.strip()
jinja["description"] = value.description
if value.params:
jinja["params"] = self.object_to_yaml(
"params", type_, value.params, multi, object_path
)
jinja["params"] = self.object_to_yaml("params", type_, value.params, multi, object_path)
return jinja
elif isinstance(value, Calculation):
variable_attributes = self.get_attributes(
value.__class__,
[
"path",
"inside_list",
"version",
"xmlfiles",
"attribute_name",
"namespace",
],
)
variable_attributes = self.get_object_informations(value, ['path', 'inside_list', 'version', 'xmlfiles', 'attribute_name', 'namespace'])
variable = CommentedMap()
if isinstance(
value, (IdentifierCalculation, IdentifierPropertyCalculation)
):
if isinstance(value, (IdentifierCalculation, IdentifierPropertyCalculation)):
variable["type"] = "identifier"
elif isinstance(value, IndexCalculation):
if isinstance(value, IndexCalculation):
variable["type"] = "index"
elif isinstance(value, NamespaceCalculation):
variable["type"] = "namespace"
for key, default in variable_attributes.items():
val = getattr(value, key)
if val != default and val is not undefined:
variable[key] = val
if "variable" in variable:
variable["variable"] = self.calc_variable_path(
object_path, variable["variable"]
)
if variable.get("type") == "identifier" and "identifier" in variable:
variable["variable"] = self.calc_variable_path(object_path, variable["variable"])
if variable.get('type') == 'identifier' and 'identifier' in variable:
del variable["type"]
if value.description:
if "\n" in value.description:
variable["description"] = LiteralScalarString(value.description.strip())
else:
variable["description"] = value.description.strip()
return variable
elif isinstance(value, Param):
param_attributes = self.get_attributes(
value.__class__, ["type", "key", "namespace"]
)
if list(param_attributes) == ["value"]:
param_attributes = self.get_object_informations(value, ["type", "key"])
if list(param_attributes) == ['value']:
variable = value.value
else:
variable = CommentedMap()
if isinstance(value, IdentifierParam):
variable["type"] = "identifier"
elif isinstance(value, IndexParam):
if isinstance(value, IndexParam):
variable["type"] = "index"
elif isinstance(value, NamespaceParam):
variable["type"] = "namespace"
for key, default in param_attributes.items():
val = getattr(value, key)
if val != default and val is not undefined:
variable[key] = val
if variable.get("type") == "identifier" and "identifier" in variable:
if variable.get('type') == 'identifier' and 'identifier' in variable:
del variable["type"]
if "variable" in variable:
variable["variable"] = self.calc_variable_path(
object_path, variable["variable"]
)
variable["variable"] = self.calc_variable_path(object_path, variable["variable"])
return {value.key: variable}
elif type_ == "port" and isinstance(value, str) and value.isnumeric():
elif type_ == 'port' and isinstance(value, str) and value.isnumeric():
return int(value)
elif key == "help" and "\n" in value:
return LiteralScalarString(value.strip())
return value
def calc_variable_path(self, object_path, variable_path):
@ -560,14 +355,13 @@ class RougailOutputFormatter:
else:
len_common_path = len(common_path) + 1
relative_object_path = object_path[len_common_path:]
final_path = "_" * (relative_object_path.count(".") + 1) + "."
return (
"_" * (relative_object_path.count(".") + 1)
+ "."
+ variable_path[len_common_path:]
)
final_path = "_" * (relative_object_path.count(".") + 1) + '.'
return "_" * (relative_object_path.count(".") + 1) + '.' + variable_path[len_common_path:]
return variable_path
def get_object_informations(self, value, excludes=[]):
return {attr: obj.get("default") for attr, obj in value.__class__.model_json_schema()["properties"].items() if attr not in excludes}
def get_parent_name(self, path):
if "." in path:
return path.rsplit(".", 1)
@ -578,17 +372,13 @@ class RougailOutputFormatter:
if not subpath:
return y
name = subpath.pop(0)
if name not in y and name.endswith("{{ identifier }}"):
search_name = name[:-16]
if search_name not in y:
search_name = name.replace("{{ identifier }}", "{{ suffix }}")
name = search_name
if name not in y and name.endswith('{{ identifier }}'):
name = name[:-16]
return _yaml(y[name])
if self.main_namespace:
subpath = path.split(".")[1:]
subpath = path.split('.')[1:]
else:
subpath = path.split(".")
subpath = path.split('.')
return _yaml(self.original_yaml)

View file

@ -1 +0,0 @@
__version__ = "0.1.0a16"

View file

@ -1,6 +1,6 @@
"""
Silique (https://www.silique.fr)
Copyright (C) 2024-2025
Copyright (C) 2024
This program is free software: you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by the
@ -29,36 +29,21 @@ load_unexist_redefine:
type: boolean
default:
jinja: >-
{% if step.output is not propertyerror and step.output == 'formatter' %}
{% if step.output == 'formatter' %}
true
{% else %}
false
{% endif %}
hidden:
jinja: >-
{% if step.output is not propertyerror and step.output == 'formatter' %}
{% if step.output == 'formatter' %}
load_unexist_redefine is always true with 'formatter' output
{% endif %}
cli:
load_config:
exists: true
redefine: true
type: boolean
default:
jinja: >-
{% if step.output is not propertyerror and step.output == 'formatter' %}
false
{% else %}
true
{% endif %}
"""
return {
"name": "formatter",
"process": "output",
"options": options,
"allow_user_data": False,
"level": 90,
}

View file

@ -4,7 +4,7 @@ Cadoles (http://www.cadoles.com)
Copyright (C) 2021
Silique (https://www.silique.fr)
Copyright (C) 2022-2025
Copyright (C) 2022-2024
This program is free software: you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by the
@ -45,33 +45,22 @@ class RougailUpgrade:
def run(
self,
file: str,
) -> dict:
file,
):
with file.open() as file_fh:
root = YAML().load(file_fh)
if not root:
root = {}
if "_version" in root:
version_name = "_version"
format_version = str(root.pop("_version"))
elif "version" in root:
version_name = "version"
format_version = str(root.pop("version"))
else:
version_name = None
format_version = self.rougailconfig["default_structural_format_version"]
if format_version not in VERSIONS:
raise Exception(f'version "{format_version}" is not a valid version')
search_function_name = get_function_name(format_version)
search_function_name = get_function_name(str(root["version"]))
function_found = False
for version, function_version in FUNCTION_VERSIONS:
if function_found and hasattr(self, function_version):
root = getattr(self, function_version)(root)
if function_version == search_function_name:
function_found = True
if version_name:
root[version_name] = float(version)
return version_name, root
if '_version' in root:
root["_version"] = float(version)
elif 'version' in root:
root["version"] = float(version)
return root
def update_1_1(
self,
@ -80,7 +69,7 @@ class RougailUpgrade:
new_root = CommentedMap()
for key, value in root.items():
if not isinstance(value, dict):
if key == "variable" and "{{ suffix }}" in value:
if key == 'variable' and "{{ suffix }}" in value:
value = value.replace("{{ suffix }}", "{{ identifier }}")
new_root[key] = value
continue
@ -105,7 +94,7 @@ class RougailUpgrade:
new_root[key] = value
for typ, obj in {
"boolean": bool,
"integer": int,
"number": int,
"string": str,
"float": float,
}.items():

View file

@ -1,4 +0,0 @@
%YAML 1.2
---
version: 1.1
...

View file

@ -1,3 +0,0 @@
%YAML 1.2
---
...

View file

@ -1,3 +0,0 @@
%YAML 1.2
---
...

View file

@ -1,6 +1,4 @@
%YAML 1.2
---
_version: 1.1
version: # a variable
...

View file

@ -1,6 +1,4 @@
%YAML 1.2
---
version: 1.1
empty:
...

View file

@ -1,4 +1,3 @@
%YAML 1.2
---
version: 1.1
@ -11,4 +10,3 @@ var2:
jinja: |-
{{ _.var1 }}
description: the value of var1
...

View file

@ -1,4 +1,3 @@
%YAML 1.2
---
version: 1.1
@ -16,4 +15,3 @@ var2:
{{ val }}
{% endfor %}
description: the value of _.var1
...

View file

@ -1,22 +0,0 @@
%YAML 1.2
---
version: 1.1
leadership:
type: leadership
hidden: true
var1: # a first variable
- a_value
var2: a_value # a first variable
var2:
description: a second variable
default:
jinja: >-
{{ var1[0] }}
params:
var1:
variable: _.leadership.var1
...

View file

@ -1,16 +0,0 @@
%YAML 1.2
---
version: 1.1
var1:
description: a first variable
type: domainname
params:
allow_ip: true
multi: true
var2:
description: a second variable
default:
variable: _.var1
...

View file

@ -1,12 +0,0 @@
%YAML 1.2
---
version: 1.1
var1: # a first variable
var2:
description: a second variable
default:
variable: _.var1
description: value of a variable!
...

View file

@ -1,18 +0,0 @@
%YAML 1.2
---
version: 1.1
var1: # a first variable
var2:
description: a second variable
default:
variable: _.var1
description: |-
value
of
a
variable!
var3: # a new variable
...

View file

@ -1,4 +1,3 @@
%YAML 1.2
---
version: 1.1
@ -13,4 +12,3 @@ var2:
description: a second variable
default:
variable: _.var1
...

View file

@ -1,6 +1,4 @@
%YAML 1.2
---
version: 1.1
var1: # a variable
...

View file

@ -1,6 +1,4 @@
%YAML 1.2
---
version: 1.1
var2: # a variable
...

View file

@ -1,6 +1,4 @@
%YAML 1.2
---
version: 1.1
without_type: non # a variable
...

View file

@ -1,4 +1,3 @@
%YAML 1.2
---
version: 1.1
@ -13,4 +12,3 @@ var4: false # the forth variable
var5: false # the fifth variable
var6: false # the sixth variable
...

View file

@ -1,4 +1,3 @@
%YAML 1.2
---
version: 1.1
@ -6,4 +5,3 @@ variable:
description: a variable
mandatory: false
default: true
...

View file

@ -1,4 +1,3 @@
%YAML 1.2
---
version: 1.1
@ -27,7 +26,7 @@ var3:
var4:
description: the forth variable
choices:
- null
-
- b
- c
mandatory: false
@ -47,4 +46,3 @@ var6:
- 2
- 3
default: 1
...

View file

@ -1,4 +1,3 @@
%YAML 1.2
---
version: 1.1
@ -9,7 +8,6 @@ var:
{% for n in trange(0, 10) %}
{{ n }}
{% endfor %}
return_type: integer
return_type: number
description: choices is 0 to 9
default: 9
...

View file

@ -1,16 +0,0 @@
%YAML 1.2
---
version: 1.1
var1:
description: the first variable
choices:
- a
- b
- c
var2:
description: the second variable
default:
variable: _.var1
...

View file

@ -1,4 +1,3 @@
%YAML 1.2
---
version: 1.1
@ -12,4 +11,3 @@ var2:
choices:
variable: _.var1
default: a
...

View file

@ -1,20 +0,0 @@
%YAML 1.2
---
version: 1.1
var1: # a second variable
- a
- b
- c
var2:
description: a first variable
choices:
variable: _.var1
default: a
var3:
description: a third variable
default:
variable: _.var2
...

View file

@ -1,22 +0,0 @@
%YAML 1.2
---
version: 1.1
var1: # a second variable
- a
- b
- c
var2:
description: a first variable
choices:
variable: _.var1
default: a
family:
var3:
description: a third variable
default:
variable: __.var2
...

View file

@ -1,4 +1,3 @@
%YAML 1.2
---
version: 1.1
@ -10,4 +9,3 @@ custom2:
description: the seconf variable
type: custom
default: value
...

View file

@ -1,4 +1,3 @@
%YAML 1.2
---
version: 1.1
@ -6,4 +5,3 @@ variable:
description: a domain name variable
type: domainname
default: my.domain.name
...

View file

@ -1,4 +1,3 @@
%YAML 1.2
---
version: 1.1
@ -8,4 +7,3 @@ variable:
params:
allow_ip: true
default: my.domain.name
...

View file

@ -1,4 +1,3 @@
%YAML 1.2
---
version: 1.1
@ -13,4 +12,3 @@ var4: 10.1 # the forth variable
var5: 10.1 # the fifth variable
var6: 10.1 # the sixth variable
...

View file

@ -1,16 +0,0 @@
%YAML 1.2
---
version: 1.1
var1: 0 # the first variable
var2: 0 # the second variable
var3: 0 # the third variable
var4: 10 # this forth variable
var5: 10 # the fifth variable
var6: 10 # the sixth variable
...

View file

@ -1,25 +0,0 @@
%YAML 1.2
---
version: 1.1
var1:
description: an IP
type: ip
default: 1.1.1.1
var2:
description: an IP in CIDR format
examples:
- 192.168.0.128/25
type: ip
params:
cidr: true
default: 1.1.1.1/24
var3:
description: an IP in CIDR format with obsolete CIDR type
type: ip
params:
cidr: true
default: 1.1.1.1/24
...

View file

@ -1,23 +0,0 @@
%YAML 1.2
---
version: 1.1
var1:
description: an network
type: network
default: 1.1.1.0
var2:
description: an network in CIDR format
type: network
params:
cidr: true
default: 1.1.1.0/24
var3:
description: an network in CIDR format with obsolete CIDR type
type: network
params:
cidr: true
default: 1.1.1.0/24
...

View file

@ -1,4 +1,3 @@
%YAML 1.2
---
version: 1.1
@ -13,4 +12,3 @@ var4: 10 # this forth variable
var5: 10 # the fifth variable
var6: 10 # the sixth variable
...

View file

@ -1,4 +1,3 @@
%YAML 1.2
---
version: 1.1
@ -15,4 +14,3 @@ variable3:
description: a port variable with integer default value
type: port
default: 8080
...

View file

@ -1,4 +1,3 @@
%YAML 1.2
---
version: 1.1
@ -9,4 +8,3 @@ var:
- '#b2b2b2'
regexp: ^#(?:[0-9a-f]{3}){1,2}$
default: '#a1a1a1'
...

View file

@ -1,20 +0,0 @@
%YAML 1.2
---
version: 1.1
var1:
description: a first variable
test:
- '#b1b1b1'
- '#b2b2b2'
regexp: ^#(?:[0-9a-f]{3}){1,2}$
default: '#a1a1a1'
var2:
description: a second variable
test:
- '#b2b1b1'
- '#b3b2b2'
default:
variable: _.var1
...

View file

@ -1,13 +0,0 @@
%YAML 1.2
---
version: 1.1
secret1:
description: the first variable
type: secret
secret2:
description: the second variable
type: secret
default: value
...

View file

@ -1,29 +0,0 @@
%YAML 1.2
---
version: 1.1
secret1:
description: the first variable
type: secret
params:
min_len: 10
secret2:
description: the second variable
type: secret
params:
max_len: 10
forbidden_char:
- $
- ^
default: value
secret3:
description: the third variable
type: secret
params:
max_len: 10
forbidden_char:
- $
default: value
...

View file

@ -1,4 +1,3 @@
%YAML 1.2
---
version: 1.1
@ -13,4 +12,3 @@ var4: value # the forth variable
var5: value # the fifth variable
var6: value # the sixth variable
...

View file

@ -1,4 +1,3 @@
%YAML 1.2
---
version: 1.1
@ -10,4 +9,3 @@ var:
- quote"
- quote"'
default: quote'
...

View file

@ -1,20 +0,0 @@
%YAML 1.2
---
version: 1.1
var1:
description: the first variable
help: |-
Multi line
Help
With useful information
var2:
description: the second variable
help: |-
Multi line
Help
With useful information
...

View file

@ -1,4 +1,3 @@
%YAML 1.2
---
version: 1.1
@ -9,4 +8,3 @@ var1:
var2:
description: the second variable
help: message with "
...

View file

@ -1,20 +0,0 @@
%YAML 1.2
---
version: 1.1
var1:
description: the first <variable>
help: |-
Multi line
<Help>
With useful information
var2:
description: the second <variable>
help: |-
Multi line
<Help>
With useful information
...

View file

@ -1,6 +1,4 @@
%YAML 1.2
---
version: 1.1
variable: quote" # a variable
...

View file

@ -1,6 +1,4 @@
%YAML 1.2
---
version: 1.1
variable: quote'" # a variable
...

View file

@ -1,6 +1,4 @@
%YAML 1.2
---
version: 1.1
variable: quote\"\' # a variable
...

View file

@ -1,6 +1,4 @@
%YAML 1.2
---
version: 1.1
variable: quote' # a variable
...

View file

@ -1,4 +1,3 @@
%YAML 1.2
---
version: 1.1
@ -11,4 +10,3 @@ variable:
params:
test_information:
information: test_information
...

View file

@ -1,10 +0,0 @@
%YAML 1.2
---
version: 1.1
variable:
description: a variable
default:
type: namespace
mandatory: false
...

View file

@ -1,14 +0,0 @@
%YAML 1.2
---
version: 1.1
variable:
description: a variable
default:
jinja: >-
{{ namespace }}
params:
namespace:
type: namespace
mandatory: false
...

View file

@ -1,4 +1,3 @@
%YAML 1.2
---
version: 1.1
@ -22,7 +21,7 @@ var3:
var4:
description: the forth variable
test:
- null
-
- test1
- test2
mandatory: false
@ -39,4 +38,3 @@ var6:
- test1
- test2
multi: true
...

View file

@ -1,4 +1,3 @@
%YAML 1.2
---
version: 1.1
@ -16,4 +15,3 @@ variable2:
- val2
multi: true
mandatory: false
...

View file

@ -1,4 +1,3 @@
%YAML 1.2
---
version: 1.1
@ -13,4 +12,3 @@ my_variable:
- variable: _.source_variable_1
- variable: _.source_variable_2
default: val1
...

View file

@ -1,4 +1,3 @@
%YAML 1.2
---
version: 1.1
@ -12,5 +11,4 @@ variable:
param1: string
param2: 1
param3: true
param4: null
...
param4:

View file

@ -1,4 +1,3 @@
%YAML 1.2
---
version: 1.1
@ -12,4 +11,3 @@ var:
information:
information: test_information
variable: _.var
...

View file

@ -1,4 +1,3 @@
%YAML 1.2
---
version: 1.1
@ -13,4 +12,3 @@ var2:
information:
information: test_information
variable: _.var1
...

View file

@ -1,4 +1,3 @@
%YAML 1.2
---
version: 1.1
@ -9,4 +8,3 @@ my_calculated_variable:
optional: true
- variable: _.my_variable_unexists
optional: true
...

View file

@ -1,4 +1,3 @@
%YAML 1.2
---
version: 1.1
@ -9,4 +8,3 @@ my_calculated_variable:
optional: true
- variable: _.my_variable
optional: true
...

View file

@ -1,13 +0,0 @@
%YAML 1.2
---
version: 1.1
my_variable: val1
my_calculated_variable:
- variable: _.my_variable
optional: true
- variable: _.my_variable_unexists
optional: true
default: value
...

View file

@ -1,4 +1,3 @@
%YAML 1.2
---
version: 1.1
@ -7,4 +6,3 @@ my_calculated_variable:
default:
variable: _.my_variable
optional: true
...

View file

@ -1,4 +1,3 @@
%YAML 1.2
---
version: 1.1
@ -7,7 +6,7 @@ my_variable:
- val2
my_calculated_variable:
multi: true
default:
variable: _.my_variable
optional: true
...

View file

@ -1,4 +1,3 @@
%YAML 1.2
---
version: 1.1
@ -6,15 +5,8 @@ var1:
description: a first variable
default:
jinja: >-
{% if var2 is defined %}
{{ var2 }}
{% elif var3 is defined %}
{{ var3 }}
{% elif var4 is defined %}
{{ var4 }}
{% else %}
{{ _.var2 }}
{% endif %}
{% if var2 is defined %} {{ var2 }} {% elif var3 is defined %} {{ var3 }} {%
elif var4 is defined %} {{ var4 }} {% else %} {{ _.var2 }} {% endif %}
description: returns a value
params:
var2:
@ -29,4 +21,3 @@ var1:
mandatory: false
var2: no # a second variable
...

View file

@ -1,4 +1,3 @@
%YAML 1.2
---
version: 1.1
@ -9,4 +8,3 @@ var2:
default:
information: test_information
variable: _.var1
...

View file

@ -1,4 +1,3 @@
%YAML 1.2
---
version: 1.1
@ -9,4 +8,3 @@ var2:
default:
information: test_information
variable: _.var1
...

View file

@ -1,4 +1,3 @@
%YAML 1.2
---
version: 1.1
@ -9,7 +8,6 @@ var:
{% for item in trange(0, 10) %}
{{ item }}
{%- endfor %}
return_type: integer
return_type: number
description: choice for 0 to 9
default: 9
...

View file

@ -1,15 +0,0 @@
%YAML 1.2
---
version: 1.1
var:
description: a variable
choices:
jinja: |-
{% for item in trange(0, 10) %}
{{ item }}
{%- endfor %}
return_type: integer
description: choice for 0 to 9
default: 9
...

View file

@ -1,4 +1,3 @@
%YAML 1.2
---
version: 1.1
@ -8,4 +7,3 @@ variable:
jinja: >-
no
description: return no
...

View file

@ -1,6 +1,4 @@
%YAML 1.2
---
version: 1.1
variable: rougail # a variable
...

View file

@ -1,4 +1,3 @@
%YAML 1.2
---
version: 1.1
@ -23,4 +22,3 @@ variable3:
params:
variable:
variable: rougail.variable
...

View file

@ -1,6 +1,4 @@
%YAML 1.2
---
version: 1.1
variable: value # a variable
...

View file

@ -1,6 +1,4 @@
%YAML 1.2
---
version: 1.1
variable: value in extra # a variable
...

View file

@ -1,4 +1,3 @@
%YAML 1.2
---
version: 1.1
@ -6,4 +5,3 @@ variable:
description: a variable
default:
variable: extra.variable
...

View file

@ -1,4 +1,3 @@
%YAML 1.2
---
version: 1.1
@ -25,4 +24,3 @@ var7: # the seventh variable
var8: # the eighth variable
- true
...

View file

@ -1,4 +1,3 @@
%YAML 1.2
---
version: 1.1
@ -12,4 +11,3 @@ custom2:
type: custom
default:
- value
...

View file

@ -1,4 +1,3 @@
%YAML 1.2
---
version: 1.1
@ -25,4 +24,3 @@ var7: # the seventh variable
var8: # the eighth variable
- 0.0
...

View file

@ -1,28 +0,0 @@
%YAML 1.2
---
version: 1.1
var1: # the first variable
- 0
var2: # the second variable
- 0
var3: # the third variable
- 0
var4: # the forth variable
- 10
var5: # the fifth variable
- 10
var6: # the sixth variable
- 10
var7: # the seventh variable
- 0
var8: # the eighth variable
- 0
...

View file

@ -0,0 +1,26 @@
---
version: 1.1
var1: # the first variable
- 0
var2: # the second variable
- 0
var3: # the third variable
- 0
var4: # the forth variable
- 10
var5: # the fifth variable
- 10
var6: # the sixth variable
- 10
var7: # the seventh variable
- 0
var8: # the eighth variable
- 0

View file

@ -1,4 +1,3 @@
%YAML 1.2
---
version: 1.1
@ -6,6 +5,5 @@ var1:
description: the second variable
default:
- value
- null
-
empty: false
...

View file

@ -1,4 +1,3 @@
%YAML 1.2
---
version: 1.1
@ -22,4 +21,3 @@ var7: # the seventh variable
var8: # the eighth variable
- value
...

View file

@ -1,7 +1,5 @@
%YAML 1.2
---
version: 1.1
variable: # a variable
- quote"
...

View file

@ -1,7 +1,5 @@
%YAML 1.2
---
version: 1.1
variable: # a variable
- quote'"
...

View file

@ -1,7 +1,5 @@
%YAML 1.2
---
version: 1.1
variable: # a variable
- quote'
...

View file

@ -1,4 +1,3 @@
%YAML 1.2
---
version: 1.1
@ -14,4 +13,3 @@ variable:
params:
test_information:
information: test_information_list
...

View file

@ -1,4 +1,3 @@
%YAML 1.2
---
version: 1.1
@ -11,4 +10,3 @@ variable2:
description: a second variable
choices:
variable: _.variable1
...

View file

@ -1,15 +0,0 @@
%YAML 1.2
---
version: 1.1
variable:
description: a variable
choices:
variable: _.unknown_variable
optional: true
default:
- a
- b
- c
default: c
...

View file

@ -1,11 +1,9 @@
%YAML 1.2
---
version: 1.1
int:
description: A limited number
params:
min_integer: 0
max_integer: 100
min_number: 0
max_number: 100
default: 10
...

View file

@ -1,11 +0,0 @@
%YAML 1.2
---
version: 1.1
int:
description: A limited integer
params:
min_integer: 0
max_integer: 100
default: 10
...

View file

@ -1,4 +1,3 @@
%YAML 1.2
---
version: 1.1
@ -6,4 +5,3 @@ variable:
description: an auto save variable
default: no
auto_save: true
...

View file

@ -1,4 +1,3 @@
%YAML 1.2
---
version: 1.1
@ -9,4 +8,3 @@ var2:
default:
variable: _.var1
auto_save: true
...

View file

@ -1,4 +1,3 @@
%YAML 1.2
---
version: 1.1
@ -17,4 +16,3 @@ var2:
_.var1 is yes
{% endif %}
description: only if the variable var1 has value "yes"
...

View file

@ -1,4 +1,3 @@
%YAML 1.2
---
version: 1.1
@ -8,4 +7,3 @@ var:
auto_save: true
mandatory: false
hidden: true
...

View file

@ -1,4 +1,3 @@
%YAML 1.2
---
version: 1.1
@ -17,4 +16,3 @@ var3:
{% if _.var1 == 'value' or _.var2 == 'blah' %}
value
{% endif %}
...

View file

@ -1,4 +1,3 @@
%YAML 1.2
---
version: 1.1
@ -17,4 +16,3 @@ var3:
{% if _.var2 is propertyerror %}
value
{% endif %}
...

View file

@ -1,23 +0,0 @@
%YAML 1.2
---
version: 1.1
var1:
description: a first variable
default: value
hidden: true
var2:
description: a second variable
disabled:
variable: _.var1
when: value
var3:
description: a third variable
default:
jinja: >-
{% if _.var1 == 'value' or _.var2 == 'blah' %}
value
{% endif %}
...

View file

@ -1,23 +0,0 @@
%YAML 1.2
---
version: 1.1
var1:
description: a first variable
default: value
hidden: true
var2:
description: a second variable
disabled:
variable: _.var1
when_not: value
var3:
description: a third variable
default:
jinja: >-
{% if _.var1 == 'value' or _.var2 == 'blah' %}
value
{% endif %}
...

View file

@ -1,18 +0,0 @@
%YAML 1.2
---
version: 1.1
var1: value # a first variable
var2:
description: a second variable
default:
variable: _.var1
hidden: true
var3:
description: a third variable
disabled:
variable: _.var2
when: value
...

Some files were not shown because too many files have changed in this diff Show more