Application specific tag of Jinja2 template in PyYAML.
It may be useful if you only want to render special tag nodes in the document, instead of whole YAML string as a template.
-
Add
Jinja2
template constructor for tag"!j2"
import yaml import jinjyaml as jy ctor = jy.Constructor() yaml.add_constructor("!j2", ctor, yaml.SafeLoader)
-
create
YAML
file1.yml
, with such contents:array: !j2 | {% for i in range(n) %} - sub{{i}}: {{loop.index}} {% endfor %}
-
load and render the
YAML
filewith open("1.yml") as fp: data = yaml.load(fp, Loader=yaml.SafeLoader) # or for the short: # data = yaml.safe_load(fp) jy.extract(data, context={"n": 3}, inplace=True) print(data)
We'll get:
{"array": [{"sub0": 1}, {"sub1": 2}, {"sub2": 3}]}
We have such YAML files:
-
sub-1.yml
:"1.1": one "1.2": two
-
sub-2.yml
:"2.1": "2.1.1": three "2.1.2": four
-
main.yml
:foo: !j2 | {% filter indent %} {% include "sub-1.yml" %} {% endfilter %} {% filter indent %} {% include "sub-2.yml" %} {% endfilter %}
execute python code:
from pprint import pprint
import jinja2
import jinjyaml as jy
import yaml
env = jinja2.Environment(loader=jinja2.FileSystemLoader("."))
ctor = jy.Constructor()
yaml.add_constructor("!j2", ctor, yaml.SafeLoader)
with open("main.yml") as fp:
doc = yaml.safe_load(fp)
obj = jy.extract(doc, env)
pprint(obj)
We'll get:
{"foo": {"1.1": "one",
"1.2": "two",
"2.1": {"2.1.1": "three", "2.1.2": "four"}}}
NOTE:
Since Jinja2's
include
andindent
do not work very nice with indention languages like Python or YAML, it's not advised to use the feature in a complex case.