Skip to content
techcode-ioPublic

About

Render jinja2 templates using the command line without python runtime.

Topics

Resources

Stars

7 stars

Watchers

1 watching

Forks

Latest commit

ย 

History

248 Commits

Folders and files

NameName
Last commit message
Last commit date
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

Temply

Render jinja2 templates on the command line without python runtime.

๐Ÿ“ฆ Prerequisites

  • uv for build system.
  • Docker or Podman for deb/rpm packaging (Linux only).

โœจ Features

  • Render jinja2 template using command line without python environment.
  • Standalone executable with jinja2 templating engine.
  • Support inclusion template rendering, from files and stdin.
  • Command line compatible with envtpl.
  • Load variables from environment, envdir, dotenv and json files.
  • Parse and serialize JSON and YAML values with filters.

๐ŸŽฏ Motivation

  • We needed a way to generate files using data sources in a container environment.
  • The solution should be standalone and delivered as a binary.

๐Ÿ”จ Workflow

Setup

The following steps will ensure your project is cloned properly.

  1. Clone repository:
    git clone https://github.com/techcode-io/temply
    cd temply
  2. Install dependencies and setup environment:
    uv sync
    uv run poe env:configure

Lint

  • To lint you have to use the workflow.
uv run poe lint

Format

  • To format you have to use the workflow.
uv run poe fmt
  • It will format the project code using ruff.

Build

  • To build you have to use the workflow.
uv run poe build
  • It will compile project code with the current environment into dist/temply.
  • It will also create a dist/temply-<version>-<os>-<arch>.tar.gz tarball.
  • On Linux, uv run poe package:deb and uv run poe package:rpm build packages from dist/temply.

Test

  • To test temply you have to use the workflow.
  • Tests are based on pytest.
uv run poe test

๐Ÿ“– Usage

Warning

By default, temply deletes the template file after a successful rendering. Use --keep-template to keep it.

Usage: temply [OPTIONS] [INPUT_FILE]

Options:
  --allow-missing         Allow missing variables.
  --keep-template         Keep original template file (it is deleted after
                          rendering by default).
  --envdir DIRECTORY      Load environment variables from directory
  --dotenv FILE           Load environment variables from dotenv file
  --json-file FILE        Load environment variables from json file
  -o, --output-file FILE  Output file path.
  --version               Show the version and exit.
  --help                  Show this message and exit.

How it works

  • We use PyInstaller to create a standalone executable.
  • This means you don't need a python runtime to run it.
  • This also means it depends on the glibc version.
  • To be compatible with a wide range of linux distributions, we build the project using an old glibc version.
  • If the binary doesn't run, you will have to rebuild it on your distribution.
  • When temply starts, it reads the template from INPUT_FILE (or stdin when omitted) and configures jinja2 to load included templates from the template directory (or the current directory for stdin).
  • It then renders the template and writes the result to the output file, or to stdout.
  • The output is written as is: temply doesn't add a trailing newline.
  • If rendering fails (undefined variable, syntax error, invalid value), temply exits with code 1, prints an error and leaves the template untouched.
  • You can use any jinja2 syntax.

Data sources

  • Variables are loaded from the following sources, each one overriding the previous ones:
    1. Environment variables.
    2. --envdir directory.
    3. --dotenv file.
    4. --json-file file.
  • This order is fixed and doesn't depend on the order of the options on the command line.

Filters

Filter Description
from_json, fromjson Parse a JSON string.
to_json, tojson Serialize a value to JSON. Replaces the jinja2 built-in tojson (no HTML escape).
from_yaml, fromyaml Parse a YAML string.
to_yaml, toyaml Serialize a value to YAML.
  • The environment(prefix) function returns the (key, value) pairs of all variables starting with prefix, sorted by key and with the prefix removed.

How to render a simple configuration

  • Before anything, note that you can render any file with any extension because jinja2 is based on text templating.
  • Create a file where you want /path/to/template.yml.tpl with the following content.
variable = '{{ variable }}'
another_one = '{{ another_one }}'
default_var = '{{ default_missing_var | default("default") }}'
  • Then launch the command below to render.
variable=foo another_one=bar temply -o /path/to/template.yml /path/to/template.yml.tpl
  • It will create a file /path/to/template.yml with the following content.
variable = 'foo'
another_one = 'bar'
default_var = 'default'

How to render a configuration from stdin

  • Launch the command below to render.
echo 'Hello {{ name }} !' | name=world temply -o /path/to/template.txt
  • It will create a file /path/to/template.txt with the following content.
Hello world !
  • Templates read from stdin can include templates relative to the current directory.

How to render an advanced configuration

  • Create a file where you want /path/to/template.yml.tpl with the following content.
{% include "include.yml.tpl" %}
  • And another one at /path/to/include.yml.tpl with the following content.
foobar="Hello world !"
  • Then launch the command below to render.
temply --keep-template -o /path/to/template.yml /path/to/template.yml.tpl
  • It will create a file /path/to/template.yml with the following content.
foobar="Hello world !"

How to render a configuration with missing environment variables

  • By default, an undefined variable is an error.
  • Create a file where you want /path/to/template.yml.tpl with the following content.
missing_var = '{{ missing_var }}'
  • Then launch the command below to render.
temply --allow-missing -o /path/to/template.yml /path/to/template.yml.tpl
  • It will create a file /path/to/template.yml with the following content.
missing_var = ''

How to render a configuration on stdout

  • Create a file where you want /path/to/template.yml.tpl with the following content.
foobar="{{ foobar }}"
  • Then launch the command below to render.
foobar='Hello world !' temply /path/to/template.yml.tpl
  • It will output on stdout the following content.
foobar="Hello world !"

How to render a configuration with a json environment variable

  • Create a file where you want /path/to/template.json.tpl with the following content.
first = {{ (json_var | from_json)[0] }}
all = {{ json_var | from_json | to_json }}
  • Then launch the command below to render.
json_var='["string", 42]' temply /path/to/template.json.tpl
  • It will output on stdout the following content.
first = string
all = ["string", 42]

How to render a configuration with a yaml environment variable

  • Create a file where you want /path/to/template.yaml.tpl with the following content.
foo = {{ (yaml_var | from_yaml).foo }}
{{ yaml_var | from_yaml | to_yaml }}
  • Then launch the command below to render.
yaml_var='{foo: bar, list: [1, 2]}' temply /path/to/template.yaml.tpl
  • It will output on stdout the following content.
foo = bar
foo: bar
list:
- 1
- 2

How to render a configuration with a wildcard environment variable

  • Create a file where you want /path/to/template.yml.tpl with the following content.
{% for key, value in environment('MY_') -%}
{{ key }} = {{ value }}
{% endfor %}
  • Then launch the command below to render.
MY_FOO=foo MY_BAR=bar temply /path/to/template.yml.tpl
  • It will output on stdout the following content.
BAR = bar
FOO = foo

How to render a configuration with an envdir

  • An envdir is a directory where each file defines a variable: the file name is the key and its content the value.
  • Trailing spaces, tabs and newlines are removed from the value, and NUL characters are replaced by newlines.
  • An empty file unsets the variable, even if it's defined in the environment.
  • Hidden files and subdirectories are ignored.
  • Create a file where you want /path/to/template.yml.tpl with the following content.
foobar="{{ FOOBAR }}"
  • Then create an envdir with a file named FOOBAR with foobar as content.
  • Then launch the command below to render.
temply --envdir /path/to/envdir /path/to/template.yml.tpl
  • It will output on stdout the following content.
foobar="foobar"

How to render a configuration with a dotenv file

  • A dotenv file contains one KEY=VALUE per line.
  • Blank lines and lines starting with # are ignored, and an optional export prefix is allowed.
  • Spaces around the key and the value are removed, as well as matching single or double quotes around the value.
  • Escape sequences, variable interpolation and multiline values aren't supported.
  • Create a file where you want /path/to/template.yml.tpl with the following content.
foobar="{{ FOOBAR }}"
  • Then create a dotenv file named dotenv with the following content.
# Comments are allowed
export FOOBAR="foobar"
  • Then launch the command below to render.
temply --dotenv /path/to/dotenv /path/to/template.yml.tpl
  • It will output on stdout the following content.
foobar="foobar"

How to render a configuration with a json file

  • A json file is either an object or a list of {"key": ..., "value": ...} objects.
  • Values keep their JSON type (string, number, list, object), and a null value unsets the variable.
  • Create a file where you want /path/to/template.yml.tpl with the following content.
foo="{{ FOO }}"
bar="{{ BAR }}"
  • Then create a json file named file.json with the following content.
{
  "FOO": "foo",
  "BAR": "bar"
}
  • Or with the following content.
[
  {
    "key": "FOO",
    "value": "foo"
  },
  {
    "key": "BAR",
    "value": "bar"
  }
]
  • Then launch the command below to render.
temply --json-file /path/to/file.json /path/to/template.yml.tpl
  • It will output on stdout the following content.
foo="foo"
bar="bar"

How to render a configuration and keep template after rendering

  • By default, temply removes the template file after rendering it.
  • If you want to keep the template, use the flag --keep-template.
  • The template is never removed when reading it from stdin or when rendering fails.

โค๏ธ Contributing

If you find this project useful here's how you can help, please click the ๐Ÿ‘๏ธ Watch button to avoid missing notifications about new versions, and give it a ๐ŸŒŸ GitHub Star!

You can also contribute by:

  • Sending a Pull Request with your awesome new features and bug fixed.
  • Be part of the community and help resolve Issues.

๐Ÿงพ License

The temply project is free and open-source software licensed under the Apache-2.0 license.

About

Render jinja2 templates using the command line without python runtime.

Topics

Resources

Stars

7 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages