Skip to main content

kannushi

PyPI - Version Python Version from PEP 621 TOML GitHub branch check runs

kannushi is a command line utility for batch rendering of Jinja templates.

In a nutshell, it takes a directory containing *.jinja files and recursively renders those templates into a given target directory, mirroring the folder structure.

Example

kannushi -j8 --vars "config/**/*.yml" src_templates/ src/

This will render Jinja template files in up to 8 parallel jobs (-j8) from src_templates/ into src/, based on data from YAML files inside config/.
Each rendered file will have the same name as its source template, minus the .jinja extension. It will also be placed at the same path relative to src/ as its source template is relative to src_templates/. So, for example src_templates/some/path/filename.ext.jinja will be rendered into src/some/path/filename.ext.
Existing files in src/ that reside at paths corresponding to templates will be overwritten. All other files in src/ will be left untouched.

As the above example suggests, extensive template-based code generation is the use case that kannushi is primarily geared towards.

If needed, the user can also provide custom Python code to pre-process the data dictionary read from --vars before it is passed to Jinja for template rendering, or to expose arbitrary Python functions to the template code (see Input Data Pre-Processing).

It can also be run in read-only verification mode, to confirm if target files are up to date with their source templates and data (see --check Mode).

Installation

Via pip:

pip install kannushi

Via uv:

uv tool install kannushi

Additional CLI Features

Expanding on the basic example above, let's look at some of kannushi's other features.

Single-Template Mode

Source and target paths can also be regular files, in which case kannushi renders one template into one output file:

kannushi --vars "config/**/*.yml" single_file.ext.jinja single_file.ext

Note that if the target path already exists, its kind must match the source path's — a file source requires a file target, and a directory source a directory target.

All features described below (--check, --diff etc.) work the same whether kannushi was called with individual files or directories.

--check Mode

kannushi can be run in read-only verification mode by adding --check to its command line arguments.

kannushi -j8 --check --vars "config/**/*.yml" src_templates/ src/

In this mode the tool doesn't write anything to disk but simply verifies that target files are consistent with their source templates, i.e. that all of them already exist and none contain "manual" modifications or are otherwise out of date, relative to freshly rendered templates. If this is not the case, the tool logs any inconsistencies found to stderr and exits non-zero.

This mode is primarily useful in scenarios where rendered files are themselves kept under version control. In such cases --check provides a non-destructive way for the user (be it an individual, a version control hook, or an automated CI script) to determine if any of the rendered files have been manually modified or deleted.

YAML Logs and Unified Diff

Likewise mostly useful in a CI context, --log and --diff arguments can be used to output additional data, suitable for subsequent processing by other scripts or tools. These are most often used in --check mode, but either or both of them can also be specified independently.

kannushi -j8 --check --log report.yml --diff changes.patch --vars "config/**/*.yml" src_templates/ src/

--log will write a YAML log file to the given path at the end of the tool's run. It captures any errors from the variable loading and processing steps, a summary of the render (including per-template render errors, if any), and — in the presence of --check — the verification results, i.e. which target files were found to be modified or missing.

--diff stores a unified diff between the current versions of target files as they exist(ed) on disk prior to the run and their newly rendered content.

Input Data Pre-Processing

For cases where using static data from YAML files doesn't quite cut it, custom Python code can also be provided to kannushi by means of the --vars-processor argument, which can be used either alone or in combination with --vars and/or --check.
For example, suppose we have a Python file like this, called processor.py in the current working directory:

# processor.py
import math
...

def custom_function_exposed_to_templates(arg):
    ...

def process_vars(vars):
    """`process_vars()` will be called by kannushi before any templates are rendered.
    `vars` is a dict-like object that will utlimately be used as the context for rendering.

    If `--vars` is given, `vars` will be pre-populated with data loaded from YAML files.
    """
    # (assuming some_variable was loaded from YAML given by --vars)
    vars.some_variable_squared = vars.some_variable * vars.some_variable
    vars.utils = {
        "custom_function": custom_function_exposed_to_templates,
        "distance": math.dist
    }
    ...

We can have kannushi make use of it like so (building on the previous example):

kannushi -j8 --vars "config/**/*.yml" --vars-processor processor.py src_templates/ src/

In this case the dictionary of input data will be read from YAML files under config/ and passed as the vars argument to the process_vars() function in processor.py, where it can undergo arbitrary modifications, before being used as the context for rendering of Jinja templates from src_templates/.

As seen in the process_vars() code example above, besides calculating some template variables on the fly, this mechanism can also be used to expose custom Python functions to the Jinja code in the rendered templates.

It's also possible to use --vars-processor alone, without --vars, provided the script's code doesn't rely on data loaded from YAML. In that case the dictionary passed as argument to process_vars() will start off empty and can be populated entirely by Python code.

Synopsis

usage: kannushi [-h] [--skip SKIP_GLOB] [-e TEMPLATE_EXT] [--vars VARS_YAML_GLOB]
                [--ignore-absent-vars-files] [--vars-duplicates {reject,merge}]
                [--vars-processor VARS_PROCESSOR_MODULE]
                [--vars-processor-func VARS_PROCESSOR_FUNCTION]
                [-j JOBS_COUNT] [--check] [--log LOG_YAML_PATH] [--diff DIFF_PATH]
                [-v] [--no-color] [-V]
                SOURCE_PATH TARGET_PATH

Renders all Jinja templates in a directory into files in another directory, preserving the folder
structure. SOURCE_PATH and TARGET_PATH may also be regular files, in which case one template is
rendered into one output file. Templates must use UTF-8 (with or without BOM), rendered files will
reflect their source templates' BOM or lack thereof.

positional arguments:
  SOURCE_PATH           EITHER directory containing Jinja templates OR a single Jinja
                        template file
  TARGET_PATH           EITHER target directory for rendered files OR the target file

options:
  -h, --help            show this help message and exit
  --skip SKIP_GLOB      glob for template files to skip when rendering (relative to SOURCE_PATH)
  -e, --ext TEMPLATE_EXT
                        file extension used for templates in SOURCE_PATH (defaults to jinja)
  --vars VARS_YAML_GLOB
                        YAML file(s) containing template variable definitions
  --ignore-absent-vars-files
                        proceed with no variables instead of failing when
                        --vars matches no files
  --vars-duplicates {reject,merge}
                        whether to reject or merge top-level template variables
                        duplicated across multiple files in VARS_YAML_GLOB
                        (defaults to reject)
  --vars-processor VARS_PROCESSOR_MODULE
                        Python file/module to use for variables dictionary pre-processing
  --vars-processor-func VARS_PROCESSOR_FUNCTION
                        single-parameter function in VARS_PROCESSOR_MODULE which vars dictionary
                        will be passed to (defaults to process_vars)
  -j, --jobs JOBS_COUNT
                        max number of parallel jobs (defaults to the number of logical CPU cores)
  --check               check if files under TARGET_PATH are consistent with their
                        templates from SOURCE_PATH, make no changes on disk, exit non-zero if
                        any inconsistencies are found
  --log LOG_YAML_PATH   output log file path (logs written as YAML)
  --diff DIFF_PATH      output path for unified diff between current and newly-rendered versions
                        of target files
  -v, --verbose         output all processed file paths, render times and additional info to
                        stdout
  --no-color            disable output coloring
  -V, --version         print kannushi version and exit

Release files for kannushi 1.2.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for kannushi 1.2.1
File Size Uploaded
kannushi-1.2.1.tar.gz 24.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for kannushi 1.2.1
File Interpreter ABI Platform
kannushi-1.2.1-py3-none-any.whl Python 3 none any Details

Total release size: 55.4 kB

Release files / kannushi-1.2.1.tar.gz

Download URL kannushi-1.2.1.tar.gz
Size 24.3 kB
Tags Source
SHA-256 checksum
How to use checksums
c6fd10c8be55adc29a2a6763f18ff77cd4bd2d1e6177961c2e3a82d2f710c8c9
BLAKE2b-256 checksum
How to use checksums
b7bff8da01afa7685d01ccb6c55fbda28681a16b149b8a60a19ea55127d56366
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.17 {"installer":{"name":"uv","version":"0.12.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / kannushi-1.2.1-py3-none-any.whl

Download URL kannushi-1.2.1-py3-none-any.whl
Size 31.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
52a0e6d847ac23a83eb22e6f44c3637e12c86579abb81c1375515b0d79166450
BLAKE2b-256 checksum
How to use checksums
e92fbe063a5fc1c1e41505dde4d7b3312061d4213795a6404a752f3bd94aa9e9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.17 {"installer":{"name":"uv","version":"0.12.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page