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: 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
$ 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;
}
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:
$ 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).
$ 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
$ 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}}
TODO. see this
- --dump-context
- --debug
$ 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
$ 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)" } }
- use kamidana's additional modules with cookiecutter . (see examples/extensions/src/02with-cookiecutter)