fix: format with default_dictionary_format_version configuration

This commit is contained in:
egarette@silique.fr 2025-05-08 12:06:15 +02:00
parent 7cc9426750
commit 34348c086e
11 changed files with 223 additions and 68 deletions

View file

@ -31,12 +31,11 @@ from ruamel.yaml.scalarstring import LiteralScalarString, FoldedScalarString, Sc
from djlint.settings import Config
from djlint.reformat import formatter
from tiramisu import undefined
from tiramisu.config import get_common_path
from rougail.convert import RougailConvert
from rougail.object_model import Variable, Family, Calculation, JinjaCalculation, IdentifierCalculation, IdentifierPropertyCalculation, NamespaceCalculation, IdentifierParam, IndexCalculation, IndexParam, NamespaceParam, Param
from rougail.utils import normalize_family
from rougail.utils import normalize_family, undefined
from .upgrade import RougailUpgrade
from .__version__ import __version__
@ -82,25 +81,57 @@ class RougailOutputFormatter:
from rougail import RougailConfig
rougailconfig = RougailConfig
rougailconfig["step.output"] = self.output_name
if 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))
# yaml.top_level_colon_align = True
self.main_namespace = rougailconfig["main_namespace"]
filenames = rougailconfig["main_dictionaries"]
if len(rougailconfig["main_dictionaries"]) > 1:
self.main_namespace = normalize_family(self.rougailconfig["main_namespace"])
self.has_default_dictionary_format_version = self.rougailconfig["default_dictionary_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_dictionaries"]
if len(filenames) > 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.config = Config()
self.config.profile = 'jinja'
self.config.line_break_after_multiline_tag = True
self.config.indent = " "
self.original_yaml = RougailUpgrade(rougailconfig).run(filename)
datas = RougailUpgrade(rougailconfig).run(filename)
self.rougail = RougailConvert(rougailconfig)
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)
self.rougail.load_config()
self.rougail.init()
self.filename_str = str(filename)
@ -119,23 +150,6 @@ class RougailOutputFormatter:
"1.1",
datas,
)
self.yaml = YAML()
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.version = '1.2'
self.yaml.explicit_start = True
self.yaml.explicit_end = True
self.default_flow_style = False
with BytesIO() as ymlfh:
self.yaml.dump(self.families[None], ymlfh)
ret = ymlfh.getvalue().decode("utf-8").strip()
return True, ret
def print(self):
ret, data = self.run()
@ -143,33 +157,21 @@ class RougailOutputFormatter:
return ret
def parse(self):
# 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
self.families[self.main_namespace][self.version_name] = float(self.rougail.version)
self.remaining = len(self.rougail.paths._data)
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)
if isinstance(obj, Variable):
self.parse_variable(path, obj)
if not version:
raise Exception(_(f'no variables in file {self.filename_str}'))
self.families[None][version_name] = float(version)
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_dictionary_format_version:
del self.families[self.main_namespace][self.version_name]
def parse_family(self, path, obj):
children = [p.rsplit('.', 1)[-1] for p in self.rougail.parents[path]]
@ -187,9 +189,9 @@ class RougailOutputFormatter:
force_keys = list(yaml_data)
type_ = obj.type
if type_ == "dynamic":
attributes = self.dynamics_attributes
attributes = self.get_attributes(self.rougail.dynamic)
else:
attributes = self.families_attributes
attributes = self.get_attributes(self.rougail.family)
for attr, default_value in attributes.items():
if attr in ["name", "path", "namespace", "version", "xmlfiles"]:
continue
@ -244,9 +246,7 @@ class RougailOutputFormatter:
force_keys = list(yaml_data)
multi = obj.multi or isinstance(obj.default, list)
type_ = obj.type
for attr, default_value in self.variables_attributes.items():
if attr in ["name", "path", "namespace", "version", "xmlfiles"]:
continue
for attr, default_value in self.get_attributes(self.rougail.variable, ["name", "path", "namespace", "version", "xmlfiles"]).items():
try:
value = getattr(obj, attr)
except AttributeError:
@ -372,12 +372,15 @@ class RougailOutputFormatter:
if value.return_type:
jinja["return_type"] = value.return_type
if value.description:
jinja["description"] = value.description
if '\n' in value.description:
jinja["description"] = LiteralScalarString(value.description)
else:
jinja["description"] = value.description
if value.params:
jinja["params"] = self.object_to_yaml("params", type_, value.params, multi, object_path)
return jinja
elif isinstance(value, Calculation):
variable_attributes = self.get_object_informations(value, ['path', 'inside_list', 'version', 'xmlfiles', 'attribute_name', 'namespace'])
variable_attributes = self.get_attributes(value.__class__, ['path', 'inside_list', 'version', 'xmlfiles', 'attribute_name', 'namespace'])
variable = CommentedMap()
if isinstance(value, (IdentifierCalculation, IdentifierPropertyCalculation)):
variable["type"] = "identifier"
@ -393,9 +396,14 @@ class RougailOutputFormatter:
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)
else:
variable["description"] = value.description
return variable
elif isinstance(value, Param):
param_attributes = self.get_object_informations(value, ["type", "key", "namespace"])
param_attributes = self.get_attributes(value.__class__, ["type", "key", "namespace"])
if list(param_attributes) == ['value']:
variable = value.value
else:
@ -434,9 +442,6 @@ class RougailOutputFormatter:
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)

View file

@ -45,22 +45,33 @@ class RougailUpgrade:
def run(
self,
file,
):
file: str,
) -> dict:
with file.open() as file_fh:
root = YAML().load(file_fh)
search_function_name = get_function_name(str(root["version"]))
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_dictionary_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)
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' in root:
root["_version"] = float(version)
elif 'version' in root:
root["version"] = float(version)
return root
if version_name:
root[version_name] = float(version)
return version_name, root
def update_1_1(
self,

View file

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

View file

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

View file

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

View file

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

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

@ -0,0 +1,18 @@
%YAML 1.2
---
version: 1.1
leadership:
description: A leadership
type: leadership
leader:
description: The leader
multi: true
mandatory: false
follower1: [] # The first follower
follower2: # The second follower
- value
...

View file

@ -0,0 +1,25 @@
%YAML 1.2
---
version: 1.1
var1:
description: A suffix variable
default:
- val1
- val2
mandatory: false
dyn{{ identifier }}:
dynamic:
variable: _.var1
var:
description: A dynamic variable
default: a value
hidden: true
var2:
description: A variable calculated
default:
variable: _.dynval1.var
...

View file

@ -0,0 +1,25 @@
%YAML 1.2
---
version: 1.1
var1:
description: A suffix variable
default:
- val1
- val2
mandatory: false
dyn{{ identifier }}:
dynamic:
variable: _.var1
var:
description: A dynamic variable
default: true
hidden: true
var2:
description: A variable calculated
default:
variable: _.dynval1.var
...

View file

@ -0,0 +1,27 @@
%YAML 1.2
---
version: 1.1
var1:
description: A suffix variable
default:
- val1
- val2
mandatory: false
dyn{{ identifier }}:
dynamic:
variable: _.var1
var:
description: A dynamic variable
default:
- a value
- a second value
hidden: true
var2:
description: A variable calculated
default:
variable: _.dynval1.var
...