Line continuation character in Jinja2 - jinja2

Is there a line continuation character in Jinja?
In Python I can write something like:
message = """\
Once apon a time, \
there lived a clever fox.\
"""
print(message)
# Once apon a time, there lived a clever fox.
Is there a statement in Jinja that would produce a similar effect to the \ character in a Python string?
{% for value in values %}
Once apon a time, ????
there lived a clever fox.
{% endfor %}
{# The above should produce:
Once apon a time, there lived a clever fox.
#}

Related

Does Jinja support variable assignment as a result of a loop?

I've been using Jinja and DBT for a month now, and despite reading a lot about it, I didn't quite figure out how to create a list from another, using a simple for loop like I would in Python.
Just a toy example:
{%- set not_wanted_columns = ['apple', 'banana'] -%}
{%- set all_columns = ['kiwi', 'peach', 'apple', 'banana', 'apricot', 'pineapple'] -%}
What I want is a list as so:
{% set filtered_columns = ['kiwi', 'peach', 'apricot', 'pineapple'] %}
Naturally, I don't want to manually write this result because the full list might be dynamic or too long. I'm not even sure if Jinja does actually support this, although I do think this is a common problem.
As you have probably read from the documentation:
Please note that assignments in loops will be cleared at the end of the iteration and cannot outlive the loop scope. Older versions of Jinja had a bug where in some circumstances it appeared that assignments would work. This is not supported.
Source: https://jinja.palletsprojects.com/en/3.1.x/templates/#for
And I guess when you are speaking about
using a simple for loop like I would in Python
What you mean here is using a list comprehension.
So, as showed in the documentation, Jinja is using filter to achieve this:
Example usage:
{{ numbers|select("odd") }}
{{ numbers|select("divisibleby", 3) }}
Similar to a generator comprehension such as:
(n for n in numbers if test_odd(n))
(n for n in numbers if test_divisibleby(n, 3))
Source: https://jinja.palletsprojects.com/en/3.1.x/templates/#jinja-filters.select
There are actual four of those filter acting as generator comprehension:
reject
rejectattr
select
selectattr
So, in your case, a reject filter would totally do the trick:
{%- set filtered_columns = all_columns
| reject('in', not_wanted_columns)
| list
-%}
But, if you really want, you could also achieve it in a for:
{%- for column in all_columns if column not in not_wanted_columns -%}
{% do filtered_columns.append(column) %}
{%- endfor -%}
The do statement being a way to use list.append() without oddities being printed out: https://jinja.palletsprojects.com/en/3.1.x/templates/#expression-statement.

dbt run-operation to call macros that have non-string arguments

Say that I want to drop the ajs schema as a clean up activity on our dev db, not as part of a regular dbt workflow
dbt run-operation drop_schema --args '{relation: ajs}'
perhaps I need to wrap drop_schema into another macro drop_schema_str(schema_str) where schema_str is the string of the schema and it is used to make a Relation object before invoking drop_schema()?
create this macro
{% macro drop_schema_str(schema) %}
{% set relation = api.Relation.create(database=target.database, schema=schema) %}
{% do drop_schema(relation) %}
{% endmacro %}
then invoke it with
dbt run-operation drop_schema_str --args '{schema: ajs}'

How to Convert a folder of csv files to json files within Jekyll

Is it possible to convert a folder of csv files to json as part of a Jekyll workflow? I currently use a python script to do this but would like to do it entirely within Jekyll
You can call your python script as part of the build process, but you'll have to make a teeny tiny plugin to do it. This also assumes you're not using github pages, because they don't like plugins.
make a _plugins directory in your site root.
Inside that directory, create csv_to_json.rb
In that ruby file, call your python script with the following code:
# The following line tells jekyll to run everything between 'do' and 'end'
# when it finishes writing the site to disk:
Jekyll::Hooks.register :site, :post_write do |_site|
# Backticks are one way to call shell commands from ruby:
`python your_script_here.py` # replace with the correct filename
end
This is untested code. Relevant documentation here and here
There are quite a few ways to do this, but I think that's the simplest for your case.
You can :
1 - Store your csv in _data/foldername (eg : _data/members) see : Jekyll's data files
2 - Put all your datas in a new array with concat filter
{% comment %} ### Create an empty array{% endcomment %}
{% assign all-members = "" | split: "" %}
{% for part in site.data.members %}
{% assign all-members = all-members | concat: part[1] %}
{% endfor %}
3 - Output datas unsing the jsonify filter : {{ all-members | jsonify }}
An all in one, a members.json file can look like :
---
layout: null
---
{% assign all-members = "" | split: "" %}
{%- for part in site.data.members %}
{% assign all-members = all-members | concat: part[1] %}
{% endfor -%}
{{ all-members | jsonify }}
Thank you to both of you. I have gone the plugin route as this is the easiest and I may need to develop another plugin at some point so I may as well learn how to make one.

How to convert single quote into double quote in jinja template file?

Hi I have a salt state file who has a ".sls" extension and it is using jinja template
There I am creating a list in jinja template. Problem is when I run that file then list converts into JSON which convert double quotation around each element into single quotation which causes error.
{%- set opentsdb_hosts = [] -%}
{%- for host in salt['pnda.opentsdb_hosts']() -%}
{%- do opentsdb_hosts.append("http://%s:%s" % (host, opentsdb_port)) -%}
{%- endfor -%}
As you can see, I am creating a list whose name is opentsdb_hosts. Each element inside opentsdb_hosts should have a double quotation around. But it is doing single quotation.
Please help.
You must be outputting opentsdb_hosts directly using {{ opentsdb_hosts }}, which outputs it in a python-friendly format, one that usually prefers single quotes over double quotes (although both quotation marks work in python as valid string literals).
To output opentsdb_hosts as json, simply use the json renderer provided by salt instead, i.e. {{ opentsdb_hosts | tojson }}.
You may use this regex_replace("'", '"') to replace the single quote with double quotes

ansible can't get inventory_hostname

I'm trying to get the short name of a server being worked on.
I have this in jinja2:
ServerAlias graphite.{{ hostvars[inventory_hostname] }}
ServerAlias graphite.{{ hostvars[inventory_hostname] }}.{{dc}}.{{subnet}}
The above just spills the whole glob of facts instead of just the short name.
This is what the hosts.yaml looks like:
graphite.experimental.com dc=lv1 subnet=coupons.lan
What you want to use is just {{ inventory_hostname }} (or {{ inventory_hostname_short }} for the short name).
The hostvars object is a way to access the variables of every host that Ansible knows about. So hostvars[inventory_hostname] will give you the object containing all known facts about the current host, hostvars['foo'] will give you the object containing all the known facts about the host 'foo', etc.
Suppose you have a group of hosts called 'db_servers' and you wanted to generate a list of the IP addresses of all those hosts in a template. Here's how you would do that:
{% for host in groups['db_servers'] %}
{{ hostvars[host]['ansible_eth0']['ipv4']['address'] }}
{% endfor %}