The background is AWS using AWS SAM templates. It's not possible to reuse template fragments like alarm definitions for canary deployments of lambda functions resulting in very long template files. My intention is to write a template engine as wrapper around the SAM templates.
After here a very simple example what I'm trying to do:
import os
from jinja2 import Environment, BaseLoader
from yaml import dump
def to_yaml(data):
return dump(data)
yaml = """
model:
data:
message: hello world
list_data:
{{ model.list_data | to_yaml | indent }}
"""
model = {
'list_data': [1, 2, 3, 4]
}
environment = Environment(loader=BaseLoader())
environment.filters.update({'to_yaml': to_yaml})
template = environment.from_string(yaml)
print(template.render(model=model))
The result is following:
model:
data:
message: hello world
list_data:
- 1
- 2
- 3
- 4
The problem I have:
- the indentation is wrong
- (nice to have) would be great when the
to_yaml
could handle the indentation itself
Any help is appreciated
I have found similar articles (from naming) but they were about reading and manipulating the YAML document without jinja2 which is not my intention.
Edit: The proposed solution with indent(6)
was right, however I don't like the indentation of the {{ ... }}
to be on first column. In another article I found the solution that PyYAML
requires an own dumper to handle the solution of YAML correctly:
class MyDumper(Dumper):
def increase_indent(self, flow=False, indentless=False):
return super(MyDumper, self).increase_indent(flow, False)
def to_yaml(data):
return dump(data, Dumper=MyDumper)
yaml = """
model:
data:
message: hello world
list_data:
{{ model.list_data | to_yaml | indent(6) }}
dict_data:
{{ model.dict_data | to_yaml | indent(6) }}
"""
model = {
'list_data': [1, 2, 3, 4],
'dict_data': {'a': [1, 2], 'b': [3, 4]}
}
environment = Environment(loader=BaseLoader())
environment.filters.update({'to_yaml': to_yaml})
template = environment.from_string(yaml)
print(template.render(model=model))
The result is then:
model:
data:
message: hello world
list_data:
- 1
- 2
- 3
- 4
dict_data:
a:
- 1
- 2
b:
- 3
- 4