command line jinja2 template (yet another j2cli)


Keywords
jinja2, cli, commandline
License
MIT
Install
pip install kamidana==0.10.0

Documentation

kamidana

kamidana is yet another jinja2's cli wrapper.

features

  • using jinja2 file as template file (basic feature)
  • various input formats support (json, yaml, toml, ...)
  • the way of lookup template is changed, relative to parent template path
  • gentle error message
  • batch execution for speed-up (via kamidana-batch)
  • rendering with individual filters (via --additionals option)
  • (useful additionals modules (e.g. kamidana.additionals.naming ...)

usage

usage: kamidana [-h] [--driver DRIVER] [--loader LOADER] [-d DATA]
                [--logging {CRITICAL,FATAL,ERROR,WARN,WARNING,INFO,DEBUG,NOTSET}] [-a ADDITIONALS] [-e EXTENSION]
                [-i {yaml,json,toml,csv,tsv,raw,env,md,markdown,spreadsheet}] [-o OUTPUT_FORMAT] [--dump-context]
                [--list-info] [--debug] [--quiet] [--dst DST]
                [template]

positional arguments:
  template

options:
  -h, --help            show this help message and exit
  --driver DRIVER       default: kamidana.driver:Driver
  --loader LOADER       default: kamidana.loader:TemplateLoader
  -d DATA, --data DATA  support yaml, json, toml
  --logging {CRITICAL,FATAL,ERROR,WARN,WARNING,INFO,DEBUG,NOTSET}
  -a ADDITIONALS, --additionals ADDITIONALS
  -e EXTENSION, --extension EXTENSION
  -i {yaml,json,toml,csv,tsv,raw,env,md,markdown,spreadsheet}, --input-format {yaml,json,toml,csv,tsv,raw,env,md,markdown,spreadsheet}
  -o OUTPUT_FORMAT, --output-format OUTPUT_FORMAT
  --dump-context        dumping loading data (used by jinja2 template)
  --list-info           listting information (for available extensions and additional modules)
  --debug
  --quiet
  --dst DST

examples

example (basic)

$ kamidana examples/readme/src/00/nginx.jinja2 --data examples/readme/src/00/data.json
server {
  listen 80;
  server_name localhost;

  root /var/www/project;
  index index.htm;

  access_log /var/log/nginx/http.access.log combined;
  error_log  /var/log/nginx/http.error.log;
}

examples/readme/src/00/nginx.jinja2

server {
  listen 80;
  server_name {{ nginx.hostname }};

  root {{ nginx.webroot }};
  index index.htm;

  access_log {{ nginx.logdir }}/http.access.log combined;
  error_log  {{ nginx.logdir }}/http.error.log;
}

examples/readme/src/00/data.json

{
  "nginx": {
    "hostname": "localhost",
    "webroot": "/var/www/project",
    "logdir": "/var/log/nginx"
  }
}

More over, passing data with stdin. (please doen't forget to add --input-format option)

$ echo '{"nginx": {"logdir": "/tmp/logs/nginx"}}' | kamidana --input-format json examples/readme/src/00/nginx.jinja2 --data examples/readme/src/00/data.json
server {
  listen 80;
  server_name localhost;

  root /var/www/project;
  index index.htm;

  access_log /tmp/logs/nginx/http.access.log combined;
  error_log  /tmp/logs/nginx/http.error.log;
}

gentle error message

if using include, but the included template is not found.

$ tree examples/readme/src/11
examples/readme/src/11
├── header.html.j2
└── main.html.j2

1 directory, 2 files
$ kamidana examples/readme/src/11/main.html.j2
------------------------------------------------------------
exception: kamidana._path.XTemplatePathNotFound
message: [Errno 2] No such file or directory: 'footer-404.html.j2'
where: examples/readme/src/11/main.html.j2
------------------------------------------------------------
examples/readme/src/11/main.html.j2:
      2: <main>
      3:   this is main contents
      4: </main>
  ->  5: {% include "footer-404.html.j2" %}

Traceback:
  File "SITE-PACKAGES/jinja2/loaders.py", line 462, in get_source
    rv = self.load_func(template)
  File "HERE/me/kamidana/kamidana/loader.py", line 27, in load
    raise XTemplatePathNotFound(filename, exc=e).with_traceback(e.__traceback__)
  File "HERE/me/kamidana/kamidana/loader.py", line 23, in load
    with open(filename) as rf:

example2 (--additionals)

builtin addtional modules

$ kamidana --additionals=kamidana.additionals.naming examples/readme/src/01/use-naming.jinja2
singular, plurals

- days|singularize -> day
- day|pluralize -> days

- people|singularize -> person
- person|pluralize -> people

to {snake_case, kebab-case, camelCase}

- fooBarBoo|snakecase -> foo_bar_boo
- fooBarBoo|kebabcase -> foo-bar-boo
- foo_bar_boo|camelcase -> fooBarBoo


more information: see kamidana.additionals.naming module

examples/readme/src/01/use-naming.jinja2

singular, plurals

- days|singularize -> {{"days"|singularize}}
- day|pluralize -> {{"day"|pluralize}}

- people|singularize -> {{"people"|singularize}}
- person|pluralize -> {{"person"|pluralize}}

to {snake_case, kebab-case, camelCase}

- fooBarBoo|snakecase -> {{"fooBarBoo"|snakecase}}
- fooBarBoo|kebabcase -> {{"fooBarBoo"|kebabcase}}
- foo_bar_boo|camelcase -> {{"foo_bar_boo"|camelcase}}


more information: see kamidana.additionals.naming module

or kamidana -a naming is also OK (shortcut).

individual additional modules

$ kamidana --additionals=examples/readme/src/01/additionals.py --data=examples/readme/src/01/data.yaml examples/readme/src/01/hello.jinja2

  bye, world!!

examples/readme/src/01/hello.jinja2

{% if 19 is night %}
  {{night}}, {{name|surprised}}
{% else %}
  {{daytime}}, {{name|surprised}}
{% endif %}

examples/readme/src/01/additionals.py

from kamidana import (
    as_filter,
    as_globals_generator,
    as_test,
)


@as_filter
def surprised(v):
    return "{}!!".format(v)


@as_globals_generator
def generate_globals():
    return {"daytime": "hello", "night": "bye"}


@as_test
def night(hour):
    return 19 <= hour or hour < 3

examples/readme/src/01/data.yaml

name: world

example3 (using jinja2 extensions)

$ kamidana -e do -e loopcontrols examples/readme/src/02/use-extension.jinja2

hello
  world
hello

## counting
- 1
- 2
- 4

## do
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

examples/readme/src/02/use-extension.jinja2

{# with with. with_ extension is used. #}
{%- with msg = "hello"%}
{{msg}}
{%- with msg = "world"%}
  {{msg}}
{%- endwith %}
{{msg}}
{%- endwith %}

## counting
{#- with break and continue. loopcontrolls extension is used. #}

{%- for i in range(10) %}
{%- if i % 3 == 0 %}{% continue %} {% endif %}
{%- if i == 5 %}{% break %} {% endif %}
- {{i}}
{%- endfor %}

## do

{%- set xs = [] %}
{%- for i in range(10) %}
{%- do xs.append(i) %}
{%- endfor %}
{{xs}}

example4 (batch execution)

TODO. see this

debugging

  • --dump-context
  • --debug

dump context

$ kamidana --dump-context --data=examples/readme/src/10/data.yaml
{
  "name": "foo",
  "age": 20,
  "friends": [
    "bar",
    "boo"
  ],
  "template_filename": null
}

and be able to merge two files.

$ kamidana --dump-context --data=examples/readme/src/10/data.yaml --data=examples/readme/src/10/data2.yaml
{
  "name": "foo",
  "age": 21,
  "friends": [
    "bar",
    "baz"
  ],
  "template_filename": null
}

then

examples/readme/src/10/data.yaml

name: foo
age: 20
friends:
  - bar
  - boo

examples/readme/src/10/data2.yaml

age: 21
friends:
  - bar
  - baz

available info (extensions and additional modules)

$ kamidana --list-info
extensions are used by `-e`, additional modules are used by `-a`.
{
  "extensions": {
    "jinja2.ext.i18n": "This extension adds gettext support to Jinja.",
    "jinja2.ext.do": "Adds a `do` tag to Jinja that works like the print statement just",
    "jinja2.ext.loopcontrols": "Adds break and continue to the template engine.",
    "jinja2.ext.debug": "A ``{% debug %}`` tag that dumps the available variables,",
    "kamidana.extensions.NamingModuleExtension": "extension create from kamidana.additionals.naming",
    "kamidana.extensions.ReaderModuleExtension": "extension create from kamidana.additionals.reader",
    "kamidana.extensions.CookiecutterAdditionalModulesExtension": "activate additional modules, see context['cookiecutter']['_additional_modules'], created from your cookiecutter.json"
  },
  "additional_modules": {
    "kamidana.additionals.env": "accessing environemt variable, via env()",
    "kamidana.additionals.naming": "Naming helpers (e.g. snakecase, kebabcase, ... pluralize, singularize)",
    "kamidana.additionals.reader": "Reading from other resources (e.g. read_from_file, read_from_command)"
  }
}

with other packages