Compare commits

..

19 commits

Author SHA1 Message Date
b2f2aa4406 bump: version 0.1.0a5 → 0.1.0a6 2025-03-28 08:32:12 +01:00
5f46162790 fix: do not add multi \n at ends of export 2025-03-28 08:32:02 +01:00
66f044bee3 bump: version 0.1.0a4 → 0.1.0a5 2025-03-27 21:45:52 +01:00
c09800521c fix: if and for in 3 lines 2025-03-27 21:45:29 +01:00
4e9e8b082e bump: version 0.1.0a3 → 0.1.0a4 2025-03-27 08:36:55 +01:00
a4eab14564 feat: format jinja template 2025-03-27 08:36:49 +01:00
88f837aa07 bump: version 0.1.0a2 → 0.1.0a3 2025-03-27 08:29:18 +01:00
03d24af05c fix: do not add namespace in param 2025-03-26 19:34:49 +01:00
2adef78db3 feat: add secret_manager support 2025-03-26 19:34:24 +01:00
9159f44efa fix: an empty variable is [] 2025-03-26 19:34:00 +01:00
75fc04c501 feat: add Namespace(Param|Calculation) support 2025-03-26 19:32:30 +01:00
99a41bd4e5 bump: version 0.1.0a1 → 0.1.0a2 2025-03-26 14:32:00 +01:00
ec8a9c0aab fix: pyproject.toml 2025-03-26 14:31:50 +01:00
232a8385a3 bump: version 0.1.0a0 → 0.1.0a1 2025-03-26 14:30:25 +01:00
ad4e3ffd6e fix: add pyproject.toml 2025-03-26 14:29:46 +01:00
29c1941993 bump: version 0.0.1a0 → 0.1.0a0 2025-02-10 09:46:36 +01:00
9c55b5aa25 feat: output return status too 2025-02-10 09:46:31 +01:00
ad707df62d bump: version 0.0.0 → 0.0.1a0 2025-01-04 11:50:39 +01:00
2227438899 fix: remove prefix_path 2025-01-04 11:50:19 +01:00
81 changed files with 560 additions and 118 deletions

53
CHANGELOG.md Normal file
View file

@ -0,0 +1,53 @@
## 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

43
pyproject.toml Normal file
View file

@ -0,0 +1,43 @@
[build-system]
build-backend = "flit_core.buildapi"
requires = ["flit_core >=3.8.0,<4"]
[project]
name = "rougail.output_formatter"
version = "0.1.0a6"
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"
update_changelog_on_bump = true
changelog_merge_prerelease = true

View file

@ -1,6 +1,6 @@
"""
Silique (https://www.silique.fr)
Copyright (C) 2024
Copyright (C) 2024-2025
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
@ -27,11 +27,14 @@ from ruamel.yaml.error import CommentMark
from ruamel.yaml.comments import CommentedSeq
from ruamel.yaml.scalarstring import LiteralScalarString, FoldedScalarString
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, IdentifierParam, IndexCalculation, IndexParam, Param
from rougail.object_model import Variable, Family, Calculation, JinjaCalculation, IdentifierCalculation, IdentifierPropertyCalculation, NamespaceCalculation, IdentifierParam, IndexCalculation, IndexParam, NamespaceParam, Param
from rougail.utils import normalize_family
from .upgrade import RougailUpgrade
@ -72,6 +75,12 @@ class RougailOutputFormatter:
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)
@ -106,11 +115,13 @@ class RougailOutputFormatter:
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
ret = ymlfh.getvalue().decode("utf-8").strip()
return True, ret
def print(self):
print(self.run())
ret, data = self.run()
print(data)
return ret
def parse(self):
# FIXME path to relative !
@ -159,7 +170,7 @@ class RougailOutputFormatter:
else:
attributes = self.families_attributes
for attr, default_value in attributes.items():
if attr in ["name", "path", "namespace", "version", "path_prefix", "xmlfiles"]:
if attr in ["name", "path", "namespace", "version", "xmlfiles"]:
continue
try:
value = getattr(obj, attr)
@ -204,7 +215,7 @@ class RougailOutputFormatter:
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", "path_prefix", "xmlfiles"]:
if attr in ["name", "path", "namespace", "version", "xmlfiles"]:
continue
try:
value = getattr(obj, attr)
@ -238,6 +249,9 @@ class RougailOutputFormatter:
# 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'}:
# shorthand notation
default = variable.get('default')
@ -294,10 +308,18 @@ class RougailOutputFormatter:
if isinstance(value, JinjaCalculation):
jinja = CommentedMap()
# replace \n to space a add index of \n (now a space) to fold_pos
jinja_values = value.jinja.strip()
jinja_values = formatter(self.config, value.jinja.strip())[:-1]
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']
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)
else:
jinja["jinja"] = LiteralScalarString(jinja_values)
if value.return_type:
@ -312,8 +334,10 @@ class RougailOutputFormatter:
variable = CommentedMap()
if isinstance(value, (IdentifierCalculation, IdentifierPropertyCalculation)):
variable["type"] = "identifier"
if isinstance(value, IndexCalculation):
elif 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:
@ -324,15 +348,17 @@ class RougailOutputFormatter:
del variable["type"]
return variable
elif isinstance(value, Param):
param_attributes = self.get_object_informations(value, ["type", "key"])
param_attributes = self.get_object_informations(value, ["type", "key", "namespace"])
if list(param_attributes) == ['value']:
variable = value.value
else:
variable = CommentedMap()
if isinstance(value, IdentifierParam):
variable["type"] = "identifier"
if isinstance(value, IndexParam):
elif 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:

View file

@ -1,6 +1,6 @@
"""
Silique (https://www.silique.fr)
Copyright (C) 2024
Copyright (C) 2024-2025
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,14 +29,14 @@ load_unexist_redefine:
type: boolean
default:
jinja: >-
{% if step.output == 'formatter' %}
{% if step.output is not propertyerror and step.output == 'formatter' %}
true
{% else %}
false
{% endif %}
hidden:
jinja: >-
{% if step.output == 'formatter' %}
{% if step.output is not propertyerror and step.output == 'formatter' %}
load_unexist_redefine is always true with 'formatter' output
{% endif %}
"""

View file

@ -4,7 +4,7 @@ Cadoles (http://www.cadoles.com)
Copyright (C) 2021
Silique (https://www.silique.fr)
Copyright (C) 2022-2024
Copyright (C) 2022-2025
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

View file

@ -0,0 +1,11 @@
---
version: 1.1
secret1:
description: the first variable
type: secret
secret2:
description: the second variable
type: secret
default: value

View file

@ -0,0 +1,8 @@
---
version: 1.1
variable:
description: a variable
default:
type: namespace
mandatory: false

View file

@ -0,0 +1,12 @@
---
version: 1.1
variable:
description: a variable
default:
jinja: >-
{{ namespace }}
params:
namespace:
type: namespace
mandatory: false

View file

@ -5,8 +5,15 @@ 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:

View file

@ -0,0 +1,24 @@
---
version: 1.1
condition: no # a conditional variable
variable1:
description: a first variable
multi: true
disabled:
jinja: |-
{% if _.condition == "yes" %}
condition is yes
{% endif %}
description: if condition is egal to "yes"
variable2:
description: a second variable
multi: true
disabled:
jinja: |-
{% if _.condition == "yes" %}
condition is yes
{% endif %}
description: if condition is egal to "yes"

View file

@ -0,0 +1,10 @@
---
version: 1.1
condition: false # a condition
variable:
description: a variable
multi: true
disabled:
variable: _.condition

View file

@ -0,0 +1,10 @@
---
version: 1.1
condition: [] # a condition
variable:
description: a variable
multi: true
disabled:
variable: _.condition

View file

@ -0,0 +1,12 @@
---
version: 1.1
condition: # a condition
- val1
- val2
variable:
description: a variable
multi: true
disabled:
variable: _.condition

View file

@ -0,0 +1,7 @@
---
version: 1.1
family:
exists: true
variable:

View file

@ -1,27 +1,36 @@
---
version: 1.1
var1: # a variable
var1: # first variable
family: # a family
var2: # a second variable
var2:
description: a second variable
test:
- string6
subfamily: # a sub family
variable: # a variable
variable: # third variable
- variable: ___.var1
- variable: __.var2
family2: # a family
var2:
description: a variable2
default:
variable: __.family.var2
var3:
test:
- string5
default: string4
subfamily: # a sub family
variable: # a variable
variable: # fourth variable
- variable: ___.var1
- variable: ___.family.var2
- variable: __.var2
- variable: __.var3

View file

@ -5,9 +5,7 @@ leader:
description: a leadership
type: leadership
leader:
description: the leader
multi: true
leader: [] # the leader
follower1: # the follower1

View file

@ -5,13 +5,9 @@ leadership:
description: A leadership
type: leadership
leader:
description: The leader
multi: true
leader: [] # The leader
follower1:
description: The first follower
multi: true
follower1: [] # The first follower
follower2: # The second follower
- value

View file

@ -8,7 +8,11 @@ int1:
type: number
default:
jinja: >-
{% if rougail.bool %}1{% else %}2{% endif %}
{% if rougail.bool %}
1
{% else %}
2
{% endif %}
description: if bool returns 1 otherwise return 2
int2:
@ -16,5 +20,9 @@ int2:
type: number
default:
jinja: >-
{% if not rougail.bool %}3{% else %}4{% endif %}
{% if not rougail.bool %}
3
{% else %}
4
{% endif %}
description: if bool returns 3 otherwise return 4

View file

@ -0,0 +1,22 @@
---
version: 1.1
leader:
description: a leadership
type: leadership
leader: # a leader
- value1
- value2
follower1: val11 # a follower
follower2: val21 # an other follower
calculate:
description: a calculated variable
multi: true
default:
jinja: |-
{{ _.leader.follower1[0] }}
unique: false

View file

@ -0,0 +1,22 @@
---
version: 1.1
leader:
description: a leadership
type: leadership
leader: # a leader
- value1
- value2
follower1: val11 # a follower
follower2: val21 # an other follower
calculate:
description: a calculated variable
multi: true
default:
jinja: |-
{{ _.leader.follower1[-1] }}
unique: false

View file

@ -0,0 +1,21 @@
---
version: 1.1
leader:
description: a leadership
type: leadership
leader: # a leader
- value1
- value2
follower1: val11 # a follower
follower2: val21 # an other follower
calculate:
description: a calculated variable
multi: true
default:
variable: _.leader.follower1
unique: false

View file

@ -0,0 +1,20 @@
---
version: 1.1
leader:
description: a leadership
type: leadership
leader: # a leader
- value1
- value2
follower1: val11 # a follower
follower2: val21 # an other follower
calculate:
description: a calculated variable
default:
jinja: >-
{{ _.leader.leader[0] }}

View file

@ -0,0 +1,20 @@
---
version: 1.1
leader:
description: a leadership
type: leadership
leader: # a leader
- value1
- value2
follower1: val11 # a follower
follower2: val21 # an other follower
calculate:
description: a calculated variable
default:
jinja: >-
{{ _.leader.leader[-1] }}

View file

@ -0,0 +1,19 @@
---
version: 1.1
leader:
description: a leadership
type: leadership
leader: # a leader
- value1
- value2
follower1: val11 # a follower
follower2: val21 # an other follower
calculate:
description: a calculated variable
default:
variable: _.leader.leader

View file

@ -5,9 +5,7 @@ leader:
description: a leadership
type: leadership
leader:
description: a leader
multi: true
leader: [] # a leader
follower1:
description: a follower

View file

@ -7,9 +7,7 @@ leader:
description: a leadership
type: leadership
leader:
description: a leader
multi: true
leader: [] # a leader
follower:
description: a follower

View file

@ -0,0 +1,25 @@
---
version: 1.1
var: # A suffix variable
- val.1
- val.2
dyn{{ identifier }}:
description: A dynamic family
dynamic:
variable: _.var
var1:
description: A dynamic variable
default:
type: identifier
var2:
description: A dynamic variable
default:
jinja: >-
{{ identifier }}
params:
identifier:
type: identifier

View file

@ -0,0 +1,21 @@
---
version: 1.1
var1:
description: A suffix variable
test:
- val1
multi: true
mandatory: false
dyn{{ identifier }}:
dynamic:
variable: _.var1
var: # A dynamic variable
var2:
description: A variable calculated
default:
variable: _.dynval1.var
optional: true

View file

@ -0,0 +1,22 @@
---
version: 1.1
var2:
description: A variable calculated
default:
variable: _.dynval1.var
optional: true
var1:
description: A suffix variable
test:
- val1
- val2
multi: true
mandatory: false
dyn{{ identifier }}:
dynamic:
variable: _.var1
var: # A dynamic variable

View file

@ -0,0 +1,24 @@
---
version: 1.1
var: # a suffix variable
- val1
- val2
my_dyn_family_{{ identifier }}:
description: a dynamic family
dynamic:
variable: _.var
propertyerror: false
var:
description: a variable inside a dynamic family
default:
type: identifier
mandatory: false
var2:
description: a variable
multi: true
default:
variable: _.my_dyn_family_{{ identifier }}.var

View file

@ -14,9 +14,7 @@ dyn{{ identifier }}:
description: a leadership
type: leadership
leader:
description: a leader
multi: true
leader: [] # a leader
follower1:
description: a follower1

View file

@ -18,9 +18,7 @@ dyn{{ identifier }}:
description: a leadership
type: leadership
leader:
description: a leader
multi: true
leader: [] # a leader
follower1:
description: a follower1

View file

@ -7,11 +7,11 @@ from rougail_tests.utils import get_structures_list, get_rougail_config, config_
excludes = [
# "24_0family_hidden_condition_sub_family",
# "16_6exists_family",
]
test_ok = get_structures_list(excludes)
# test_ok = [Path('../rougail-tests/structures/20_9family_absolute')]
# test_ok = [Path('../rougail-tests/structures/00_9default_calculation_param_optional')]
def idfn(fixture_value):
@ -32,7 +32,7 @@ def _test_structural_files(file_name, namespace, rougailconfig):
rougailconfig['step.output'] = 'formatter'
##################################
config = None
generated_output = RougailOutput(config, rougailconfig=rougailconfig).run()
generated_output = RougailOutput(config, rougailconfig=rougailconfig).run()[1] + '\n'
output_file = get_output_director(namespace) / file_name.parent.parent.name / file_name.parent.name / file_name.name
if not output_file.is_file():
if not output_file.parent.is_dir():