<!-- *** GENERATED FILE - DO NOT EDIT *** -->
<!-- To modify this file, edit README.md.template and launch 'make doc' -->
# jinja-tree
## What is it?
`jinja-tree` is a CLI utility to process [jinja (jinja2)](https://jinja.palletsprojects.com/) templates
recursively in a directory tree.
It is very configurable and very easy to extend with its included plugin system.
The default behavior is to recursively search for files with a given extension (`.template` for example) and to process the context with [Jinja (Jinja2)](https://jinja.palletsprojects.com/) templates engine reading the context variables from:
- a configuration file
- environment variables
- dotenv files
Then, the processed content is written into another file with the same name/path but with the configured extension (`.template` by default) removed. The original file can also be deleted (but this is not the default behavior).
<details>
<summary>Full example about overall operation (in default mode)</summary>
Note: this is only the **default behavior** as you can tune this with your own plugins!
Let's imagine the following directory structure:
```
/foo/
/foo/README.md.template
/foo/bar/baz.py.template
/foo/bar/another.file
```
And execute `jinja-tree /foo` with the default configuration.
We get:
```
/foo/
/foo/README.md.template
/foo/README.md <= NEW FILE FROM README.md.template jinja2 processing
/foo/bar/baz.py.template
/foo/bar/baz.py <= NEW FILE FROM baz.py.template jinja2 processing
/foo/bar/another.file
```
</details>
## What's it for?
Your imagination is your limit 😅 but it's very useful for maintaining DRY documentation (for example `your-cli --help` output automatically updated in a markdown file), configuration files with default values read in code, including common blocks in different files...
**So it's a great tool for maintaining repositories in general.**
> [!TIP]
> Do you cant real-life examples? You can find some details about how we use it in this repository for:
>
> - [getting `jinja-tree --help` output automatically added (and updated) in this README](https://github.com/fabien-marty/jinja-tree/blob/main/docs/details-about-real-life-example1.md)
> - [getting a reference TOML configuration file rendered with default values read from code](https://github.com/fabien-marty/jinja-tree/blob/main/docs/details-about-real-life-example2.md)
> [!NOTE]
> Another "action" plugin will be soon 🕒 provided to bootstrap directory trees from templates (like with the [cookiecutter](https://github.com/fabien-marty/jinja-tree/blob/main/https://github.com/cookiecutter/cookiecutter) project).
## Features
#### 1️⃣ Easy to extend
`jinja-tree` includes a plugin system. You can override the default behavior with your own plugins.
There are two extension points:
- context plugins: to provide context variables to Jinja templates
- file plugins: to change the way how `jinja-tree` finds files to process (including target files)
See [this specification documentation page](https://github.com/fabien-marty/jinja-tree/blob/main/docs/details-about-plugins.md) for more details.
#### 2️⃣ Very configurable
`jinja-tree` is very configurable. You can configure global options via CLI options or a configuration file.
Plugins are configurable via the configuration file.
See [this specification documentation page](https://github.com/fabien-marty/jinja-tree/blob/main/docs/details-about-configuration.md) for more details.
#### 3️⃣ Embedded extensions
`jinja-tree` includes some extensions to Jinja templates engine:
- [to execute some commands (and get the corresponding output)](https://github.com/fabien-marty/jinja-tree/blob/main/jinja_tree/app/embedded_extensions/shell.py)
- [to parse JSON strings into Python objects)](https://github.com/fabien-marty/jinja-tree/blob/main/jinja_tree/app/embedded_extensions/from_json.py)
- ..
<details>
<summary>Usage examples</summary>
#### `shell` extension
```jinja
{{ "date"|shell() }}
```
=> will render something like: `Sun Jan 28 15:11:44 CET 2024`
#### `from_json` extension
```bash
export MYENV='["foo", "bar", "baz"]'
(
cat <<EOF
{% for item in MYENV|from_json() -%}
- {{ item }}
{% endfor %}
EOF
) | jinja-stdin
```
=> will render something like:
```
- foo
- bar
- bar
```
</details>
See [this directory](https://github.com/fabien-marty/jinja-tree/blob/main/jinja_tree/app/embedded_extensions/) for others
#### 4️⃣ Full Jinja / Jinja2 support (including "includes" and "inheritance")
`jinja-tree` has several options for Jinja "search paths". So you can use Jinja "includes" and "inheritance" features.
## Installation
`pip install jinja-tree`
> [!TIP]
> If you want to get a better readability of `jinja-tree` output (colors...), you can also use `pip install rich` to install
> this **optional** dependency.
> [!NOTE]
> A docker image is also available. You can use it to avoid any specific installation.
> See at the end of the "Usage" section for more details.
## Usage
### Main CLI
```
jinja-tree .
```
> [!NOTE]
> The `.` in the previous command in the "root directory" (the directory `jinja-tree` will explore recursively to find files to process). You can replace it with any directory you want. By using `.`, you will process all files in the current directory and its subdirectories.
<details>
<summary>Main CLI options</summary>
```
Usage: jinja-tree [OPTIONS] ROOT_DIR
Process a directory tree with the Jinja / Jinja2 templating system.
Arguments:
ROOT_DIR root directory [required]
Options:
--config-file TEXT config file path (default: first '.jinja-
tree.toml' file found up from current
working dir), can also be see with
JINJA_TREE_CONFIG_FILE env var [env var:
JINJA_TREE_CONFIG_FILE]
--log-level TEXT log level (DEBUG, INFO, WARNING or ERROR)
[default: INFO]
--verbose / --no-verbose increase verbosity of the DEBUG log level
(note: this forces log-level = DEBUG)
[default: no-verbose]
--extra-search-path PATH Search path to jinja (can be used multiple
times)
--add-cwd-to-search-path / --no-add-cwd-to-search-path
add current working directory (CWD) to jinja
search path
--add-root-dir-to-search-path / --no-add-root-dir-to-search-path
add root directory to jinja search path
--jinja-extension TEXT jinja extension to load
--context-plugin TEXT context plugins (full python class path, can
be used multiple times)
--action-plugin TEXT action plugin (full python class path, can
be used multiple times)
--strict-undefined / --no-strict-undefined
if set, raise an error if a variable does
not exist in context
--blank-run / --no-blank-run if set, execute a blank run (without
modifying or deleting anything) [default:
no-blank-run]
--disable-embedded-jinja-extensions / --no-disable-embedded-jinja-extensions
disable embedded jinja extensions
--help Show this message and exit.
```
</details>
### Bonus CLI (if you want to process only one file but with the same behavior)
```bash
cat /path/to/your/file/to/process | jinja-stdin >/path/to/your/processed/file
```
or (if you want to process only a string):
```console
$ export FOO=bar
$ echo "Hello {{FOO}}" | jinja-stdin
Hello bar
```
<details>
<summary>Bonus CLI options</summary>
```
Usage: jinja-stdin [OPTIONS]
Process the standard input with Jinja templating system and return the
result on the standard output.
Options:
--config-file TEXT config file path (default: first '.jinja-
tree.toml' file found up from current
working dir), can also be see with
JINJA_TREE_CONFIG_FILE env var [env var:
JINJA_TREE_CONFIG_FILE]
--log-level TEXT log level (DEBUG, INFO, WARNING or ERROR)
[default: INFO]
--verbose / --no-verbose increase verbosity of the DEBUG log level
(note: this forces log-level = DEBUG)
[default: no-verbose]
--extra-search-path PATH Search path to jinja (can be used multiple
times)
--add-cwd-to-search-path / --no-add-cwd-to-search-path
add current working directory (CWD) to jinja
search path
--jinja-extension TEXT jinja extension to load
--context-plugin TEXT context plugins (full python class path, can
be used multiple times)
--strict-undefined / --no-strict-undefined
if set, raise an error if a variable does
not exist in context
--disable-embedded-jinja-extensions / --no-disable-embedded-jinja-extensions
disable embedded jinja extensions
--help Show this message and exit.
```
</details>
### Docker image
A docker image is also available. You can use it this way:
```bash
docker run -t -v $(pwd):/workdir --user=$(id -u) ghcr.io/fabien-marty/jinja-tree:latest /workdir
```
*(we mount the current directory in the `/workdir` directory in the container and execute `jinja-tree` in this `/workdir` directory)*
> [!WARNING]
> If you plan to use environment variables with the docker image, you will have to use (possibly multiple times) the `-e VAR=VALUE` option to pass them to the container.
> With docker, it's more practical to use a `.env` (dotenv) file as it will be automatically mounted in the container.
If you want to add some CLI options, you can add them like in this example:
```bash
docker run -t -v $(pwd):/workdir --user=$(id -u) ghcr.io/fabien-marty/jinja-tree:latest --verbose /workdir
```
*(we added `--verbose` just before the `/workdir` argument)*
<details>
<summary>If you want to use the `jinja-stdin` CLI with docker?</summary>
```bash
echo "FOO {{ BAR }}" |docker run -i -v $(pwd):/workdir -e BAR=BAZ --user=$(id -u) --entrypoint jinja-stdin ghcr.io/fabien-marty/jinja-tree:latest
```
*(it will output `FOO BAZ`)*
</details>
Raw data
{
"_id": null,
"home_page": "https://github.com/fabien-marty/jinja-tree",
"name": "jinja-tree",
"maintainer": null,
"docs_url": null,
"requires_python": "<4.0,>=3.8",
"maintainer_email": null,
"keywords": "jinja, jinja2, cli, tree",
"author": "Fabien MARTY",
"author_email": "fabien.marty@botify.com",
"download_url": "https://files.pythonhosted.org/packages/c5/8f/d31ebb84f5aac2b400a177fa02bb32fa43a5faf621b6e8d7e5a6f2fe04c6/jinja_tree-0.6.1.tar.gz",
"platform": null,
"description": "<!-- *** GENERATED FILE - DO NOT EDIT *** -->\n<!-- To modify this file, edit README.md.template and launch 'make doc' -->\n\n# jinja-tree\n\n## What is it?\n\n`jinja-tree` is a CLI utility to process [jinja (jinja2)](https://jinja.palletsprojects.com/) templates\nrecursively in a directory tree.\n\nIt is very configurable and very easy to extend with its included plugin system.\n\nThe default behavior is to recursively search for files with a given extension (`.template` for example) and to process the context with [Jinja (Jinja2)](https://jinja.palletsprojects.com/) templates engine reading the context variables from:\n\n- a configuration file\n- environment variables \n- dotenv files \n\nThen, the processed content is written into another file with the same name/path but with the configured extension (`.template` by default) removed. The original file can also be deleted (but this is not the default behavior).\n\n<details>\n\n<summary>Full example about overall operation (in default mode)</summary>\n\nNote: this is only the **default behavior** as you can tune this with your own plugins!\n\nLet's imagine the following directory structure:\n\n```\n/foo/\n/foo/README.md.template\n/foo/bar/baz.py.template\n/foo/bar/another.file\n```\n\nAnd execute `jinja-tree /foo` with the default configuration.\n\nWe get:\n\n```\n/foo/\n/foo/README.md.template\n/foo/README.md <= NEW FILE FROM README.md.template jinja2 processing\n/foo/bar/baz.py.template\n/foo/bar/baz.py <= NEW FILE FROM baz.py.template jinja2 processing \n/foo/bar/another.file\n```\n\n</details>\n\n## What's it for?\n\nYour imagination is your limit \ud83d\ude05 but it's very useful for maintaining DRY documentation (for example `your-cli --help` output automatically updated in a markdown file), configuration files with default values read in code, including common blocks in different files...\n\n**So it's a great tool for maintaining repositories in general.**\n\n> [!TIP]\n> Do you cant real-life examples? You can find some details about how we use it in this repository for:\n> \n> - [getting `jinja-tree --help` output automatically added (and updated) in this README](https://github.com/fabien-marty/jinja-tree/blob/main/docs/details-about-real-life-example1.md)\n> - [getting a reference TOML configuration file rendered with default values read from code](https://github.com/fabien-marty/jinja-tree/blob/main/docs/details-about-real-life-example2.md)\n\n> [!NOTE]\n> Another \"action\" plugin will be soon \ud83d\udd52 provided to bootstrap directory trees from templates (like with the [cookiecutter](https://github.com/fabien-marty/jinja-tree/blob/main/https://github.com/cookiecutter/cookiecutter) project).\n\n## Features\n\n#### 1\ufe0f\u20e3 Easy to extend \n\n`jinja-tree` includes a plugin system. You can override the default behavior with your own plugins.\n\nThere are two extension points:\n\n- context plugins: to provide context variables to Jinja templates\n- file plugins: to change the way how `jinja-tree` finds files to process (including target files)\n\nSee [this specification documentation page](https://github.com/fabien-marty/jinja-tree/blob/main/docs/details-about-plugins.md) for more details.\n\n#### 2\ufe0f\u20e3 Very configurable\n\n`jinja-tree` is very configurable. You can configure global options via CLI options or a configuration file. \n\nPlugins are configurable via the configuration file.\n\nSee [this specification documentation page](https://github.com/fabien-marty/jinja-tree/blob/main/docs/details-about-configuration.md) for more details.\n\n#### 3\ufe0f\u20e3 Embedded extensions\n\n`jinja-tree` includes some extensions to Jinja templates engine:\n\n- [to execute some commands (and get the corresponding output)](https://github.com/fabien-marty/jinja-tree/blob/main/jinja_tree/app/embedded_extensions/shell.py)\n- [to parse JSON strings into Python objects)](https://github.com/fabien-marty/jinja-tree/blob/main/jinja_tree/app/embedded_extensions/from_json.py)\n- ..\n\n<details>\n\n<summary>Usage examples</summary>\n\n#### `shell` extension\n\n\n```jinja\n{{ \"date\"|shell() }}\n```\n\n=> will render something like: `Sun Jan 28 15:11:44 CET 2024`\n\n\n#### `from_json` extension\n\n\n```bash\nexport MYENV='[\"foo\", \"bar\", \"baz\"]'\n\n(\n cat <<EOF\n{% for item in MYENV|from_json() -%}\n- {{ item }}\n{% endfor %}\nEOF\n) | jinja-stdin\n```\n\n\n=> will render something like:\n\n```\n- foo\n- bar\n- bar\n```\n\n</details>\n\nSee [this directory](https://github.com/fabien-marty/jinja-tree/blob/main/jinja_tree/app/embedded_extensions/) for others\n\n#### 4\ufe0f\u20e3 Full Jinja / Jinja2 support (including \"includes\" and \"inheritance\")\n\n`jinja-tree` has several options for Jinja \"search paths\". So you can use Jinja \"includes\" and \"inheritance\" features.\n\n## Installation\n\n`pip install jinja-tree`\n\n> [!TIP]\n> If you want to get a better readability of `jinja-tree` output (colors...), you can also use `pip install rich` to install \n> this **optional** dependency.\n\n> [!NOTE]\n> A docker image is also available. You can use it to avoid any specific installation.\n> See at the end of the \"Usage\" section for more details.\n\n## Usage\n\n### Main CLI\n\n```\njinja-tree .\n```\n\n> [!NOTE]\n> The `.` in the previous command in the \"root directory\" (the directory `jinja-tree` will explore recursively to find files to process). You can replace it with any directory you want. By using `.`, you will process all files in the current directory and its subdirectories.\n\n<details>\n\n<summary>Main CLI options</summary>\n\n```\nUsage: jinja-tree [OPTIONS] ROOT_DIR\n\n Process a directory tree with the Jinja / Jinja2 templating system.\n\nArguments:\n ROOT_DIR root directory [required]\n\nOptions:\n --config-file TEXT config file path (default: first '.jinja-\n tree.toml' file found up from current\n working dir), can also be see with\n JINJA_TREE_CONFIG_FILE env var [env var:\n JINJA_TREE_CONFIG_FILE]\n --log-level TEXT log level (DEBUG, INFO, WARNING or ERROR)\n [default: INFO]\n --verbose / --no-verbose increase verbosity of the DEBUG log level\n (note: this forces log-level = DEBUG)\n [default: no-verbose]\n --extra-search-path PATH Search path to jinja (can be used multiple\n times)\n --add-cwd-to-search-path / --no-add-cwd-to-search-path\n add current working directory (CWD) to jinja\n search path\n --add-root-dir-to-search-path / --no-add-root-dir-to-search-path\n add root directory to jinja search path\n --jinja-extension TEXT jinja extension to load\n --context-plugin TEXT context plugins (full python class path, can\n be used multiple times)\n --action-plugin TEXT action plugin (full python class path, can\n be used multiple times)\n --strict-undefined / --no-strict-undefined\n if set, raise an error if a variable does\n not exist in context\n --blank-run / --no-blank-run if set, execute a blank run (without\n modifying or deleting anything) [default:\n no-blank-run]\n --disable-embedded-jinja-extensions / --no-disable-embedded-jinja-extensions\n disable embedded jinja extensions\n --help Show this message and exit.\n\n``` \n\n</details>\n\n### Bonus CLI (if you want to process only one file but with the same behavior)\n\n```bash\ncat /path/to/your/file/to/process | jinja-stdin >/path/to/your/processed/file\n```\n\nor (if you want to process only a string):\n\n\n```console\n$ export FOO=bar\n$ echo \"Hello {{FOO}}\" | jinja-stdin\nHello bar\n```\n\n\n<details>\n\n<summary>Bonus CLI options</summary>\n\n```\nUsage: jinja-stdin [OPTIONS]\n\n Process the standard input with Jinja templating system and return the\n result on the standard output.\n\nOptions:\n --config-file TEXT config file path (default: first '.jinja-\n tree.toml' file found up from current\n working dir), can also be see with\n JINJA_TREE_CONFIG_FILE env var [env var:\n JINJA_TREE_CONFIG_FILE]\n --log-level TEXT log level (DEBUG, INFO, WARNING or ERROR)\n [default: INFO]\n --verbose / --no-verbose increase verbosity of the DEBUG log level\n (note: this forces log-level = DEBUG)\n [default: no-verbose]\n --extra-search-path PATH Search path to jinja (can be used multiple\n times)\n --add-cwd-to-search-path / --no-add-cwd-to-search-path\n add current working directory (CWD) to jinja\n search path\n --jinja-extension TEXT jinja extension to load\n --context-plugin TEXT context plugins (full python class path, can\n be used multiple times)\n --strict-undefined / --no-strict-undefined\n if set, raise an error if a variable does\n not exist in context\n --disable-embedded-jinja-extensions / --no-disable-embedded-jinja-extensions\n disable embedded jinja extensions\n --help Show this message and exit.\n\n``` \n\n</details>\n\n### Docker image\n\nA docker image is also available. You can use it this way:\n\n```bash\ndocker run -t -v $(pwd):/workdir --user=$(id -u) ghcr.io/fabien-marty/jinja-tree:latest /workdir\n```\n\n*(we mount the current directory in the `/workdir` directory in the container and execute `jinja-tree` in this `/workdir` directory)*\n\n> [!WARNING]\n> If you plan to use environment variables with the docker image, you will have to use (possibly multiple times) the `-e VAR=VALUE` option to pass them to the container. \n> With docker, it's more practical to use a `.env` (dotenv) file as it will be automatically mounted in the container.\n\nIf you want to add some CLI options, you can add them like in this example:\n\n```bash\ndocker run -t -v $(pwd):/workdir --user=$(id -u) ghcr.io/fabien-marty/jinja-tree:latest --verbose /workdir\n```\n\n*(we added `--verbose` just before the `/workdir` argument)*\n\n<details>\n\n<summary>If you want to use the `jinja-stdin` CLI with docker?</summary>\n\n\n```bash\necho \"FOO {{ BAR }}\" |docker run -i -v $(pwd):/workdir -e BAR=BAZ --user=$(id -u) --entrypoint jinja-stdin ghcr.io/fabien-marty/jinja-tree:latest\n```\n\n\n*(it will output `FOO BAZ`)*\n\n</details>",
"bugtrack_url": null,
"license": "MIT",
"summary": "CLI to process jinja (jinja2) templates in a directory tree",
"version": "0.6.1",
"project_urls": {
"Homepage": "https://github.com/fabien-marty/jinja-tree",
"Repository": "https://github.com/fabien-marty/jinja-tree"
},
"split_keywords": [
"jinja",
" jinja2",
" cli",
" tree"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "b3939227329d5f7f44bda7bdae09f85252fe2a75025e990787577f2bc90ab5c6",
"md5": "62c7f4782b686ce2635a43eadebcb812",
"sha256": "b79f3cee2cc119339ae2965ad5f09783ce321bf5bc3b8a37391562ab1f74a1ed"
},
"downloads": -1,
"filename": "jinja_tree-0.6.1-py3-none-any.whl",
"has_sig": false,
"md5_digest": "62c7f4782b686ce2635a43eadebcb812",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": "<4.0,>=3.8",
"size": 24089,
"upload_time": "2024-08-24T06:14:09",
"upload_time_iso_8601": "2024-08-24T06:14:09.034553Z",
"url": "https://files.pythonhosted.org/packages/b3/93/9227329d5f7f44bda7bdae09f85252fe2a75025e990787577f2bc90ab5c6/jinja_tree-0.6.1-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "c58fd31ebb84f5aac2b400a177fa02bb32fa43a5faf621b6e8d7e5a6f2fe04c6",
"md5": "c7cb69443a86fbcba9cb04e89c86c584",
"sha256": "cb5d1eb447028cd9445169f259270d7a6536c97e67f15b6da0a14aac71b8132c"
},
"downloads": -1,
"filename": "jinja_tree-0.6.1.tar.gz",
"has_sig": false,
"md5_digest": "c7cb69443a86fbcba9cb04e89c86c584",
"packagetype": "sdist",
"python_version": "source",
"requires_python": "<4.0,>=3.8",
"size": 19280,
"upload_time": "2024-08-24T06:14:10",
"upload_time_iso_8601": "2024-08-24T06:14:10.147416Z",
"url": "https://files.pythonhosted.org/packages/c5/8f/d31ebb84f5aac2b400a177fa02bb32fa43a5faf621b6e8d7e5a6f2fe04c6/jinja_tree-0.6.1.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-08-24 06:14:10",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "fabien-marty",
"github_project": "jinja-tree",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "jinja-tree"
}