makejinja 2.3.5__tar.gz → 2.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {makejinja-2.3.5 → makejinja-2.4.0}/PKG-INFO +27 -32
- {makejinja-2.3.5 → makejinja-2.4.0}/README.md +24 -29
- {makejinja-2.3.5 → makejinja-2.4.0}/makejinja/__init__.py +4 -2
- {makejinja-2.3.5 → makejinja-2.4.0}/makejinja/app.py +48 -30
- {makejinja-2.3.5 → makejinja-2.4.0}/makejinja/config.py +17 -8
- makejinja-2.3.5/makejinja/loader.py → makejinja-2.4.0/makejinja/plugin.py +17 -18
- {makejinja-2.3.5 → makejinja-2.4.0}/pyproject.toml +7 -3
- {makejinja-2.3.5 → makejinja-2.4.0}/LICENSE +0 -0
- {makejinja-2.3.5 → makejinja-2.4.0}/makejinja/__main__.py +0 -0
- {makejinja-2.3.5 → makejinja-2.4.0}/makejinja/cli.py +0 -0
- {makejinja-2.3.5 → makejinja-2.4.0}/makejinja/py.typed +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: makejinja
|
|
3
|
-
Version: 2.
|
|
4
|
-
Summary:
|
|
3
|
+
Version: 2.4.0
|
|
4
|
+
Summary: Generate entire directory structures using Jinja templates with support for external data and custom plugins.
|
|
5
5
|
Home-page: https://mirkolenz.github.io/makejinja/
|
|
6
6
|
License: MIT
|
|
7
7
|
Keywords: jinja2,home-assistant,hassio,dashboard,lovelace,template,generator,cli,tool,library
|
|
@@ -33,24 +33,25 @@ Requires-Dist: immutables (>=0.20,<0.21)
|
|
|
33
33
|
Requires-Dist: jinja2 (>=3.1,<4.0)
|
|
34
34
|
Requires-Dist: pyyaml (>=6.0,<7.0)
|
|
35
35
|
Requires-Dist: rich-click (>=1.7,<2.0)
|
|
36
|
-
Requires-Dist: typed-settings[attrs,cattrs,click] (>=23.1,<
|
|
36
|
+
Requires-Dist: typed-settings[attrs,cattrs,click] (>=23.1,<25)
|
|
37
37
|
Project-URL: Documentation, https://mirkolenz.github.io/makejinja/makejinja/cli.html
|
|
38
38
|
Project-URL: Repository, https://github.com/mirkolenz/makejinja
|
|
39
39
|
Description-Content-Type: text/markdown
|
|
40
40
|
|
|
41
41
|
<!-- markdownlint-disable MD033 MD041 -->
|
|
42
|
+
<h2><p align="center">makejinja</p></h2>
|
|
42
43
|
<p align="center">
|
|
43
44
|
<img width="256px" alt="makejinja logo" src="https://raw.githubusercontent.com/mirkolenz/makejinja/main/assets/logo.png" />
|
|
44
45
|
</p>
|
|
45
46
|
<p align="center">
|
|
46
47
|
<a href="https://pypi.org/project/makejinja/">PyPI</a> |
|
|
48
|
+
<a href="https://github.com/users/mirkolenz/packages/container/package/makejinja">Docker</a> |
|
|
47
49
|
<a href="https://mirkolenz.github.io/makejinja">Docs</a> |
|
|
48
50
|
<a href="https://github.com/mirkolenz/makejinja/tree/main/tests/data">Example</a> |
|
|
49
|
-
<a href="https://jinja.palletsprojects.com/en/3.1.x/templates">
|
|
51
|
+
<a href="https://jinja.palletsprojects.com/en/3.1.x/templates">Jinja reference</a>
|
|
50
52
|
</p>
|
|
51
53
|
<p align="center">
|
|
52
|
-
|
|
53
|
-
Use it to easily generate complex Home Assistant dashboards!
|
|
54
|
+
Generate entire directory structures using Jinja templates with support for external data and custom plugins.
|
|
54
55
|
</p>
|
|
55
56
|
|
|
56
57
|
---
|
|
@@ -58,22 +59,18 @@ Description-Content-Type: text/markdown
|
|
|
58
59
|
# makejinja
|
|
59
60
|
|
|
60
61
|
makejinja can be used to automatically generate files from [Jinja templates](https://jinja.palletsprojects.com/en/3.1.x/templates).
|
|
61
|
-
|
|
62
|
-
|
|
62
|
+
It is conceptually similar to [Ansible templates](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/template_module.html) since both are built on top of Jinja.
|
|
63
|
+
However, makejinja is a standalone tool that can be used without Ansible and offers some advanced features like custom plugins.
|
|
63
64
|
A use case for this tool is generating config files for [Home Assistant](https://www.home-assistant.io/):
|
|
64
65
|
Using the same language that the built-in templates use, you can greatly simplify your configuration.
|
|
65
66
|
An [example for Home Assistant](https://github.com/mirkolenz/makejinja/tree/main/tests/data) can be found in the tests directory.
|
|
66
67
|
|
|
67
|
-
##
|
|
68
|
+
## Highlights
|
|
68
69
|
|
|
69
|
-
- Recursively
|
|
70
|
+
- Recursively render nested directories containing template files to a common output directory.
|
|
70
71
|
- Load data files containing variables to use in your Jinja templates from YAML, TOML, and Python files.
|
|
71
|
-
-
|
|
72
|
-
-
|
|
73
|
-
- Tailor the whitespace behavior to your needs.
|
|
74
|
-
- Use custom delimiters for Jinja blocks/comments/variables.
|
|
75
|
-
- Modify _all_ init options for the Jinja environment.
|
|
76
|
-
- Write custom **Python loaders** that implement a subset of our fully typed [abstract loader class](https://mirkolenz.github.io/makejinja/makejinja/loader.html#AbstractLoader)
|
|
72
|
+
- Write custom [plugins](https://mirkolenz.github.io/makejinja/makejinja/plugin.html#Plugin) to extend the functionality of makejinja.
|
|
73
|
+
- Adjust all Jinja options (e.g., whitespace behavior and delimiters) to your needs via CLI flags or a config file.
|
|
77
74
|
|
|
78
75
|
## Installation
|
|
79
76
|
|
|
@@ -82,32 +79,30 @@ It can be used as a CLI tool or as a Python library.
|
|
|
82
79
|
|
|
83
80
|
### PIP
|
|
84
81
|
|
|
85
|
-
makejinja is available
|
|
82
|
+
makejinja is available on [PyPI](https://pypi.org/project/makejinja/) and can be installed via `pip`:
|
|
86
83
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
`pipx install makejinja`
|
|
93
|
-
|
|
94
|
-
You can then directly invoke the app as follows:
|
|
95
|
-
|
|
96
|
-
`makejinja -i ./input -o ./output`
|
|
84
|
+
```shell
|
|
85
|
+
pip install makejinja
|
|
86
|
+
makejinja -i ./input -o ./output
|
|
87
|
+
```
|
|
97
88
|
|
|
98
89
|
### Nix
|
|
99
90
|
|
|
100
91
|
If you use the `nix` package manager, you can add this repository as an input to your flake and use `makejinja.packages.${system}.default` or apply the overlay `makejinja.overlays.default`.
|
|
101
|
-
You can also run it directly
|
|
92
|
+
You can also run it directly as follows:
|
|
102
93
|
|
|
103
|
-
|
|
94
|
+
```shell
|
|
95
|
+
nix run github:mirkolenz/makejinja -- -i ./input -o ./output
|
|
96
|
+
```
|
|
104
97
|
|
|
105
98
|
### Docker
|
|
106
99
|
|
|
107
|
-
We automatically publish an image
|
|
108
|
-
To use it, mount a directory to the container and pass the options as the command
|
|
100
|
+
We automatically publish an image to the [GitHub Container Registry](https://ghcr.io/mirkolenz/makejinja).
|
|
101
|
+
To use it, mount a directory to the container and pass the options as the command:
|
|
109
102
|
|
|
110
|
-
|
|
103
|
+
```shell
|
|
104
|
+
docker run --rm -v $(pwd)/data:/data ghcr.io/mirkolenz/makejinja:latest -i /data/input -o /data/output
|
|
105
|
+
```
|
|
111
106
|
|
|
112
107
|
## Usage in Terminal / Command Line
|
|
113
108
|
|
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
<!-- markdownlint-disable MD033 MD041 -->
|
|
2
|
+
<h2><p align="center">makejinja</p></h2>
|
|
2
3
|
<p align="center">
|
|
3
4
|
<img width="256px" alt="makejinja logo" src="https://raw.githubusercontent.com/mirkolenz/makejinja/main/assets/logo.png" />
|
|
4
5
|
</p>
|
|
5
6
|
<p align="center">
|
|
6
7
|
<a href="https://pypi.org/project/makejinja/">PyPI</a> |
|
|
8
|
+
<a href="https://github.com/users/mirkolenz/packages/container/package/makejinja">Docker</a> |
|
|
7
9
|
<a href="https://mirkolenz.github.io/makejinja">Docs</a> |
|
|
8
10
|
<a href="https://github.com/mirkolenz/makejinja/tree/main/tests/data">Example</a> |
|
|
9
|
-
<a href="https://jinja.palletsprojects.com/en/3.1.x/templates">
|
|
11
|
+
<a href="https://jinja.palletsprojects.com/en/3.1.x/templates">Jinja reference</a>
|
|
10
12
|
</p>
|
|
11
13
|
<p align="center">
|
|
12
|
-
|
|
13
|
-
Use it to easily generate complex Home Assistant dashboards!
|
|
14
|
+
Generate entire directory structures using Jinja templates with support for external data and custom plugins.
|
|
14
15
|
</p>
|
|
15
16
|
|
|
16
17
|
---
|
|
@@ -18,22 +19,18 @@
|
|
|
18
19
|
# makejinja
|
|
19
20
|
|
|
20
21
|
makejinja can be used to automatically generate files from [Jinja templates](https://jinja.palletsprojects.com/en/3.1.x/templates).
|
|
21
|
-
|
|
22
|
-
|
|
22
|
+
It is conceptually similar to [Ansible templates](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/template_module.html) since both are built on top of Jinja.
|
|
23
|
+
However, makejinja is a standalone tool that can be used without Ansible and offers some advanced features like custom plugins.
|
|
23
24
|
A use case for this tool is generating config files for [Home Assistant](https://www.home-assistant.io/):
|
|
24
25
|
Using the same language that the built-in templates use, you can greatly simplify your configuration.
|
|
25
26
|
An [example for Home Assistant](https://github.com/mirkolenz/makejinja/tree/main/tests/data) can be found in the tests directory.
|
|
26
27
|
|
|
27
|
-
##
|
|
28
|
+
## Highlights
|
|
28
29
|
|
|
29
|
-
- Recursively
|
|
30
|
+
- Recursively render nested directories containing template files to a common output directory.
|
|
30
31
|
- Load data files containing variables to use in your Jinja templates from YAML, TOML, and Python files.
|
|
31
|
-
-
|
|
32
|
-
-
|
|
33
|
-
- Tailor the whitespace behavior to your needs.
|
|
34
|
-
- Use custom delimiters for Jinja blocks/comments/variables.
|
|
35
|
-
- Modify _all_ init options for the Jinja environment.
|
|
36
|
-
- Write custom **Python loaders** that implement a subset of our fully typed [abstract loader class](https://mirkolenz.github.io/makejinja/makejinja/loader.html#AbstractLoader)
|
|
32
|
+
- Write custom [plugins](https://mirkolenz.github.io/makejinja/makejinja/plugin.html#Plugin) to extend the functionality of makejinja.
|
|
33
|
+
- Adjust all Jinja options (e.g., whitespace behavior and delimiters) to your needs via CLI flags or a config file.
|
|
37
34
|
|
|
38
35
|
## Installation
|
|
39
36
|
|
|
@@ -42,32 +39,30 @@ It can be used as a CLI tool or as a Python library.
|
|
|
42
39
|
|
|
43
40
|
### PIP
|
|
44
41
|
|
|
45
|
-
makejinja is available
|
|
42
|
+
makejinja is available on [PyPI](https://pypi.org/project/makejinja/) and can be installed via `pip`:
|
|
46
43
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
`pipx install makejinja`
|
|
53
|
-
|
|
54
|
-
You can then directly invoke the app as follows:
|
|
55
|
-
|
|
56
|
-
`makejinja -i ./input -o ./output`
|
|
44
|
+
```shell
|
|
45
|
+
pip install makejinja
|
|
46
|
+
makejinja -i ./input -o ./output
|
|
47
|
+
```
|
|
57
48
|
|
|
58
49
|
### Nix
|
|
59
50
|
|
|
60
51
|
If you use the `nix` package manager, you can add this repository as an input to your flake and use `makejinja.packages.${system}.default` or apply the overlay `makejinja.overlays.default`.
|
|
61
|
-
You can also run it directly
|
|
52
|
+
You can also run it directly as follows:
|
|
62
53
|
|
|
63
|
-
|
|
54
|
+
```shell
|
|
55
|
+
nix run github:mirkolenz/makejinja -- -i ./input -o ./output
|
|
56
|
+
```
|
|
64
57
|
|
|
65
58
|
### Docker
|
|
66
59
|
|
|
67
|
-
We automatically publish an image
|
|
68
|
-
To use it, mount a directory to the container and pass the options as the command
|
|
60
|
+
We automatically publish an image to the [GitHub Container Registry](https://ghcr.io/mirkolenz/makejinja).
|
|
61
|
+
To use it, mount a directory to the container and pass the options as the command:
|
|
69
62
|
|
|
70
|
-
|
|
63
|
+
```shell
|
|
64
|
+
docker run --rm -v $(pwd)/data:/data ghcr.io/mirkolenz/makejinja:latest -i /data/input -o /data/output
|
|
65
|
+
```
|
|
71
66
|
|
|
72
67
|
## Usage in Terminal / Command Line
|
|
73
68
|
|
|
@@ -10,7 +10,9 @@
|
|
|
10
10
|
While mainly intended to be used as a command line tool, makejinja can also be from Python directly.
|
|
11
11
|
"""
|
|
12
12
|
|
|
13
|
-
from . import cli, config,
|
|
13
|
+
from . import cli, config, plugin
|
|
14
14
|
from .app import makejinja
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
loader = plugin
|
|
17
|
+
|
|
18
|
+
__all__ = ["makejinja", "config", "plugin", "loader", "cli"]
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import itertools
|
|
1
2
|
import json
|
|
2
3
|
import os
|
|
3
4
|
import shutil
|
|
@@ -15,7 +16,7 @@ from jinja2.utils import import_string
|
|
|
15
16
|
from rich import print
|
|
16
17
|
|
|
17
18
|
from makejinja.config import Config
|
|
18
|
-
from makejinja.
|
|
19
|
+
from makejinja.plugin import Data, MutableData, PathFilter, Plugin
|
|
19
20
|
|
|
20
21
|
__all__ = ["makejinja"]
|
|
21
22
|
|
|
@@ -38,9 +39,16 @@ def makejinja(config: Config):
|
|
|
38
39
|
config.output.mkdir(exist_ok=True, parents=True)
|
|
39
40
|
|
|
40
41
|
env = init_jinja_env(config, data)
|
|
42
|
+
plugins: list[Plugin] = []
|
|
41
43
|
|
|
42
|
-
for
|
|
43
|
-
|
|
44
|
+
for plugin_name in itertools.chain(config.plugins, config.loaders):
|
|
45
|
+
plugins.append(load_plugin(plugin_name, env, data, config))
|
|
46
|
+
|
|
47
|
+
plugin_path_filters: list[PathFilter] = []
|
|
48
|
+
|
|
49
|
+
for plugin in plugins:
|
|
50
|
+
if hasattr(plugin, "path_filters"):
|
|
51
|
+
plugin_path_filters.extend(plugin.path_filters())
|
|
44
52
|
|
|
45
53
|
# Save rendered files to avoid duplicate work
|
|
46
54
|
# Even if two files are in two separate dirs, they will have the same template name (i.e., relative path)
|
|
@@ -57,7 +65,12 @@ def makejinja(config: Config):
|
|
|
57
65
|
handle_input_file(user_input_path, config, env, rendered_files)
|
|
58
66
|
elif user_input_path.is_dir():
|
|
59
67
|
handle_input_dir(
|
|
60
|
-
user_input_path,
|
|
68
|
+
user_input_path,
|
|
69
|
+
config,
|
|
70
|
+
env,
|
|
71
|
+
rendered_files,
|
|
72
|
+
rendered_dirs,
|
|
73
|
+
plugin_path_filters,
|
|
61
74
|
)
|
|
62
75
|
|
|
63
76
|
postprocess_rendered_dirs(config, rendered_dirs)
|
|
@@ -122,6 +135,7 @@ def handle_input_dir(
|
|
|
122
135
|
env: Environment,
|
|
123
136
|
rendered_files: abc.MutableMapping[Path, Path],
|
|
124
137
|
rendered_dirs: abc.MutableMapping[Path, Path],
|
|
138
|
+
plugin_path_filters: abc.Sequence[abc.Callable[[Path], bool]],
|
|
125
139
|
) -> None:
|
|
126
140
|
input_paths = (
|
|
127
141
|
input_path
|
|
@@ -133,7 +147,13 @@ def handle_input_dir(
|
|
|
133
147
|
relative_path = input_path.relative_to(user_input_path)
|
|
134
148
|
output_path = generate_output_path(config, relative_path)
|
|
135
149
|
|
|
136
|
-
|
|
150
|
+
exclude_pattern_match = any(
|
|
151
|
+
input_path.match(x) for x in config.exclude_patterns
|
|
152
|
+
)
|
|
153
|
+
path_filter_match = any(
|
|
154
|
+
not path_filter(input_path) for path_filter in plugin_path_filters
|
|
155
|
+
)
|
|
156
|
+
if exclude_pattern_match or path_filter_match:
|
|
137
157
|
if not config.quiet:
|
|
138
158
|
print(f"Skip excluded path '{input_path}'")
|
|
139
159
|
|
|
@@ -169,14 +189,6 @@ def init_jinja_env(
|
|
|
169
189
|
config: Config,
|
|
170
190
|
data: Data,
|
|
171
191
|
) -> Environment:
|
|
172
|
-
# If the user-provided ordering of the inputs shall be respected, use this snippet
|
|
173
|
-
# loaders: list[BaseLoader] = []
|
|
174
|
-
# for path in config.inputs:
|
|
175
|
-
# if path.is_dir():
|
|
176
|
-
# loaders.append(FileSystemLoader(path))
|
|
177
|
-
# elif path.is_file():
|
|
178
|
-
# loaders.append(DictLoader({path.name: path.read_text()}))
|
|
179
|
-
|
|
180
192
|
file_loader = DictLoader(
|
|
181
193
|
{path.name: path.read_text() for path in config.inputs if path.is_file()}
|
|
182
194
|
)
|
|
@@ -299,8 +311,10 @@ def load_data(config: Config) -> dict[str, Any]:
|
|
|
299
311
|
return data
|
|
300
312
|
|
|
301
313
|
|
|
302
|
-
def
|
|
303
|
-
|
|
314
|
+
def load_plugin(
|
|
315
|
+
plugin_name: str, env: Environment, data: Data, config: Config
|
|
316
|
+
) -> Plugin:
|
|
317
|
+
cls: type[Plugin] = import_string(plugin_name)
|
|
304
318
|
sig_params = signature(cls).parameters
|
|
305
319
|
params: dict[str, Any] = {}
|
|
306
320
|
|
|
@@ -310,29 +324,33 @@ def process_loader(loader_name: str, env: Environment, data: Data):
|
|
|
310
324
|
params["environment"] = env
|
|
311
325
|
if sig_params.get("data"):
|
|
312
326
|
params["data"] = data
|
|
327
|
+
if sig_params.get("config"):
|
|
328
|
+
params["config"] = config
|
|
329
|
+
|
|
330
|
+
plugin = cls(**params)
|
|
313
331
|
|
|
314
|
-
|
|
332
|
+
if hasattr(plugin, "globals"):
|
|
333
|
+
env.globals.update({func.__name__: func for func in plugin.globals()})
|
|
315
334
|
|
|
316
|
-
if hasattr(
|
|
317
|
-
env.globals.update({func.__name__: func for func in
|
|
335
|
+
if hasattr(plugin, "functions"):
|
|
336
|
+
env.globals.update({func.__name__: func for func in plugin.functions()})
|
|
318
337
|
|
|
319
|
-
if hasattr(
|
|
320
|
-
env.globals.update(
|
|
338
|
+
if hasattr(plugin, "data"):
|
|
339
|
+
env.globals.update(plugin.data())
|
|
321
340
|
|
|
322
|
-
if hasattr(
|
|
323
|
-
env.
|
|
341
|
+
if hasattr(plugin, "extensions"):
|
|
342
|
+
load_extensions(env, plugin.extensions())
|
|
324
343
|
|
|
325
|
-
if hasattr(
|
|
326
|
-
|
|
344
|
+
if hasattr(plugin, "filters"):
|
|
345
|
+
env.filters.update({func.__name__: func for func in plugin.filters()})
|
|
327
346
|
|
|
328
|
-
if hasattr(
|
|
329
|
-
env.
|
|
347
|
+
if hasattr(plugin, "tests"):
|
|
348
|
+
env.tests.update({func.__name__: func for func in plugin.tests()})
|
|
330
349
|
|
|
331
|
-
if hasattr(
|
|
332
|
-
env.
|
|
350
|
+
if hasattr(plugin, "policies"):
|
|
351
|
+
env.policies.update(plugin.policies())
|
|
333
352
|
|
|
334
|
-
|
|
335
|
-
env.policies.update(loader.policies())
|
|
353
|
+
return plugin
|
|
336
354
|
|
|
337
355
|
|
|
338
356
|
def render_dir(input: Path, output: Path, config: Config) -> None:
|
|
@@ -18,7 +18,6 @@ from jinja2.defaults import (
|
|
|
18
18
|
BLOCK_START_STRING,
|
|
19
19
|
COMMENT_END_STRING,
|
|
20
20
|
COMMENT_START_STRING,
|
|
21
|
-
KEEP_TRAILING_NEWLINE,
|
|
22
21
|
LINE_COMMENT_PREFIX,
|
|
23
22
|
LINE_STATEMENT_PREFIX,
|
|
24
23
|
NEWLINE_SEQUENCE,
|
|
@@ -31,6 +30,8 @@ frozendict = immutables.Map
|
|
|
31
30
|
|
|
32
31
|
|
|
33
32
|
class Undefined(Enum):
|
|
33
|
+
"""How to handle undefined variables."""
|
|
34
|
+
|
|
34
35
|
default = DefaultUndefined
|
|
35
36
|
chainable = ChainableUndefined
|
|
36
37
|
debug = DebugUndefined
|
|
@@ -153,8 +154,8 @@ class Whitespace:
|
|
|
153
154
|
""",
|
|
154
155
|
)
|
|
155
156
|
keep_trailing_newline: bool = ts.option(
|
|
156
|
-
default=
|
|
157
|
-
click={"param_decls": "--keep-trailing-newline"},
|
|
157
|
+
default=True,
|
|
158
|
+
click={"param_decls": "--keep-trailing-newline/--strip-trailing-newline"},
|
|
158
159
|
help="""
|
|
159
160
|
Preserve the trailing newline when rendering templates.
|
|
160
161
|
The default is `False`, which causes a single newline, if present, to be stripped from the end of the template.
|
|
@@ -219,7 +220,7 @@ class Config:
|
|
|
219
220
|
default=False,
|
|
220
221
|
click={"param_decls": "--keep-jinja-suffix"},
|
|
221
222
|
help="""
|
|
222
|
-
Decide whether the specified `jinja-suffix` is removed from the file after rendering.
|
|
223
|
+
Decide whether the specified `jinja-suffix` is removed from the file name after rendering.
|
|
223
224
|
""",
|
|
224
225
|
)
|
|
225
226
|
keep_empty: bool = ts.option(
|
|
@@ -269,6 +270,14 @@ class Config:
|
|
|
269
270
|
default=tuple(),
|
|
270
271
|
click={
|
|
271
272
|
"param_decls": ("--loader", "-l"),
|
|
273
|
+
"hidden": True,
|
|
274
|
+
},
|
|
275
|
+
help="Deprecated, use `--plugin` instead.",
|
|
276
|
+
)
|
|
277
|
+
plugins: tuple[str, ...] = ts.option(
|
|
278
|
+
default=tuple(),
|
|
279
|
+
click={
|
|
280
|
+
"param_decls": ("--plugin", "-p"),
|
|
272
281
|
},
|
|
273
282
|
help="""
|
|
274
283
|
Use custom Python code to adjust the used Jinja environment to your needs.
|
|
@@ -277,8 +286,8 @@ class Config:
|
|
|
277
286
|
In addition, you may add an `__init__` function that receives two positional arguments:
|
|
278
287
|
the created Jinja environment and the data parsed from the files supplied to makejinja's `data` option.
|
|
279
288
|
This allows you to apply arbitrary logic to makejinja.
|
|
280
|
-
An import path can be specified either in dotted notation (`your.custom.
|
|
281
|
-
or with a colon as object delimiter (`your.custom:
|
|
289
|
+
An import path can be specified either in dotted notation (`your.custom.Plugin`)
|
|
290
|
+
or with a colon as object delimiter (`your.custom:Plugin`).
|
|
282
291
|
**Note:** This option may be passed multiple times to pass a list of values.
|
|
283
292
|
""",
|
|
284
293
|
)
|
|
@@ -290,7 +299,7 @@ class Config:
|
|
|
290
299
|
"show_default": "current working directory",
|
|
291
300
|
},
|
|
292
301
|
help="""
|
|
293
|
-
In order to load
|
|
302
|
+
In order to load plugins or Jinja extensions, the PYTHONPATH variable needs to be patched.
|
|
294
303
|
The default value works for most use cases, but you may load other paths as well.
|
|
295
304
|
""",
|
|
296
305
|
)
|
|
@@ -360,7 +369,7 @@ OPTION_GROUPS = {
|
|
|
360
369
|
"options": [
|
|
361
370
|
"--data",
|
|
362
371
|
"--data-var",
|
|
363
|
-
"--
|
|
372
|
+
"--plugin",
|
|
364
373
|
"--import-path",
|
|
365
374
|
"--extension",
|
|
366
375
|
"--undefined",
|
|
@@ -1,24 +1,13 @@
|
|
|
1
1
|
from collections import abc
|
|
2
|
-
from
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
from typing import Any, Protocol
|
|
3
4
|
|
|
4
5
|
from jinja2 import Environment
|
|
5
6
|
from jinja2.ext import Extension
|
|
6
7
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
"Extension",
|
|
11
|
-
"Extensions",
|
|
12
|
-
"Filter",
|
|
13
|
-
"Filters",
|
|
14
|
-
"Function",
|
|
15
|
-
"Functions",
|
|
16
|
-
"Test",
|
|
17
|
-
"Tests",
|
|
18
|
-
"Policies",
|
|
19
|
-
"MutableData",
|
|
20
|
-
"Data",
|
|
21
|
-
)
|
|
8
|
+
from makejinja.config import Config
|
|
9
|
+
|
|
10
|
+
__all__ = ["Plugin"]
|
|
22
11
|
|
|
23
12
|
Extensions = abc.Sequence[type[Extension]]
|
|
24
13
|
Filter = abc.Callable[[Any], Any]
|
|
@@ -30,10 +19,14 @@ Tests = abc.Sequence[Test]
|
|
|
30
19
|
Policies = abc.Mapping[str, Any]
|
|
31
20
|
MutableData = abc.MutableMapping[str, Any]
|
|
32
21
|
Data = abc.Mapping[str, Any]
|
|
22
|
+
PathFilter = abc.Callable[[Path], bool]
|
|
23
|
+
PathFilters = abc.Sequence[PathFilter]
|
|
24
|
+
|
|
33
25
|
|
|
26
|
+
class Plugin(Protocol):
|
|
27
|
+
"""Extend the functionality of makejinja with a plugin implementing a subset of this protocol."""
|
|
34
28
|
|
|
35
|
-
|
|
36
|
-
def __init__(self, *, env: Environment, data: Data) -> None:
|
|
29
|
+
def __init__(self, *, env: Environment, data: Data, config: Config) -> None:
|
|
37
30
|
pass
|
|
38
31
|
|
|
39
32
|
def functions(self) -> Functions:
|
|
@@ -54,6 +47,12 @@ class AbstractLoader:
|
|
|
54
47
|
def extensions(self) -> Extensions:
|
|
55
48
|
return []
|
|
56
49
|
|
|
50
|
+
def path_filters(self) -> PathFilters:
|
|
51
|
+
return []
|
|
52
|
+
|
|
57
53
|
# Deprecated: Use functions() and data() instead
|
|
58
54
|
def globals(self) -> Functions:
|
|
59
55
|
return []
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
AbstractLoader = Plugin
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "makejinja"
|
|
3
|
-
version = "2.
|
|
4
|
-
description = "
|
|
3
|
+
version = "2.4.0"
|
|
4
|
+
description = "Generate entire directory structures using Jinja templates with support for external data and custom plugins."
|
|
5
5
|
authors = ["Mirko Lenz <mirko@mirkolenz.com>"]
|
|
6
6
|
license = "MIT"
|
|
7
7
|
readme = "README.md"
|
|
@@ -49,7 +49,11 @@ python = "^3.11"
|
|
|
49
49
|
jinja2 = "^3.1"
|
|
50
50
|
pyyaml = "^6.0"
|
|
51
51
|
rich-click = "^1.7"
|
|
52
|
-
typed-settings = { version = "
|
|
52
|
+
typed-settings = { version = ">=23.1, <25", extras = [
|
|
53
|
+
"attrs",
|
|
54
|
+
"cattrs",
|
|
55
|
+
"click",
|
|
56
|
+
] }
|
|
53
57
|
immutables = "^0.20"
|
|
54
58
|
|
|
55
59
|
[tool.poetry.group.dev.dependencies]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|