diff --git a/.gitignore b/.gitignore
index 9f431dd..8308954 100644
--- a/.gitignore
+++ b/.gitignore
@@ -35,3 +35,6 @@ nosetests.xml
.pytest_cache
dist/
+env/
+*.iml
+.python-version
diff --git a/README.md b/README.md
index 13579e6..e38ccbb 100644
--- a/README.md
+++ b/README.md
@@ -17,15 +17,20 @@ Usage: jinja2 [options]
Options:
--version show program's version number and exit
-h, --help show this help message and exit
- --format=FORMAT format of input variables: auto, ini, json,
+ --format=FORMAT format of input variables: auto, env, ini, json,
querystring, yaml, yml
-e EXTENSIONS, --extension=EXTENSIONS
extra jinja2 extensions to load
+ -I INCLUDES, --includes=INCLUDES
+ extra jinja2 template directory to search for
+ (included) templates
-D key=value Define template variable in the form of key=value
-s SECTION, --section=SECTION
Use only this section from the configuration
--strict Disallow undefined variables to be used within the
template
+ -o FILE, --outfile=FILE
+ File to use for output. Default is stdout.
```
## Optional YAML support
diff --git a/jinja2cli/cli.py b/jinja2cli/cli.py
index 95a2b68..b84abf6 100644
--- a/jinja2cli/cli.py
+++ b/jinja2cli/cli.py
@@ -142,7 +142,7 @@ def _load_querystring():
import urllib.parse as urlparse
def _parse_qs(data):
- """ Extend urlparse to allow objects in dot syntax.
+ """Extend urlparse to allow objects in dot syntax.
>>> _parse_qs('user.first_name=Matt&user.last_name=Robenolt')
{'user': {'first_name': 'Matt', 'last_name': 'Robenolt'}}
@@ -212,11 +212,13 @@ def _parse_env(data):
}
-def render(template_path, data, extensions, strict=False):
+def render(template_path, data, extensions, strict=False, includes=None):
+ includes = [] if includes is None else includes
+
from jinja2 import Environment, FileSystemLoader, StrictUndefined
env = Environment(
- loader=FileSystemLoader(os.path.dirname(template_path)),
+ loader=FileSystemLoader([os.path.dirname(template_path)] + includes),
extensions=extensions,
keep_trailing_newline=True,
)
@@ -311,7 +313,9 @@ def cli(opts, args):
out = codecs.getwriter("utf8")(out)
- out.write(render(template_path, data, extensions, opts.strict))
+ out.write(
+ render(template_path, data, extensions, opts.strict, includes=opts.includes)
+ )
out.flush()
return 0
@@ -378,6 +382,14 @@ def main():
action="append",
default=["do", "with_", "autoescape", "loopcontrols"],
)
+ parser.add_option(
+ "-I",
+ "--includes",
+ help="extra jinja2 template directory to search for (included) templates",
+ dest="includes",
+ action="append",
+ default=[],
+ )
parser.add_option(
"-D",
help="Define template variable in the form of key=value",
diff --git a/tests/files/maindir_template.j2 b/tests/files/maindir_template.j2
new file mode 100644
index 0000000..7917609
--- /dev/null
+++ b/tests/files/maindir_template.j2
@@ -0,0 +1 @@
+{% include 'template.j2' %}
diff --git a/tests/files/subdir/subdir_template.j2 b/tests/files/subdir/subdir_template.j2
new file mode 100644
index 0000000..7917609
--- /dev/null
+++ b/tests/files/subdir/subdir_template.j2
@@ -0,0 +1 @@
+{% include 'template.j2' %}
diff --git a/tests/test_jinja2cli.py b/tests/test_jinja2cli.py
index 181a8bd..0b44167 100644
--- a/tests/test_jinja2cli.py
+++ b/tests/test_jinja2cli.py
@@ -1,4 +1,6 @@
import os
+import json
+import subprocess
from jinja2cli import cli
@@ -23,3 +25,60 @@ def test_absolute_path():
output = cli.render(path, {"title": title}, [])
assert output == title
assert type(output) == cli.text_type
+
+
+def test_cmd_succeeds():
+ template = "files/maindir_template.j2"
+ title = "Greatest Title 1"
+ ctx = json.dumps({"title": title})
+ echo_proc = subprocess.Popen(["echo", ctx], stdout=subprocess.PIPE, shell=False)
+ jinja_proc = subprocess.Popen(
+ ["jinja2", template],
+ stdin=echo_proc.stdout,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ shell=False,
+ )
+ assert jinja_proc.wait() == 0
+ assert jinja_proc.stderr.readlines() == []
+ assert jinja_proc.stdout.readlines() == [(title + "\n").encode()]
+
+
+def test_cmd_fails_without_includes_flag():
+ template = "files/subdir/subdir_template.j2"
+ title = "Greatest Title 2"
+ context = json.dumps({"title": title})
+ echo_args = ["echo", context]
+ jinja_args = ["jinja2", template]
+ echo_proc = subprocess.Popen(echo_args, stdout=subprocess.PIPE, shell=False)
+ jinja_proc = subprocess.Popen(
+ jinja_args,
+ stdin=echo_proc.stdout,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ shell=False,
+ )
+ assert jinja_proc.wait() == 1
+ jinja_err = jinja_proc.stderr.readlines()
+ assert "jinja2.exceptions.TemplateNotFound" in jinja_err[-1].decode("utf-8")
+ assert jinja_proc.stdout.readlines() == []
+
+
+def test_cmd_succeeds_with_includes_flag():
+ template = "files/subdir/subdir_template.j2"
+ title = "Greatest Title 3"
+ ctx = json.dumps({"title": title})
+ template_root = "files"
+ echo_args = ["echo", ctx]
+ jinja_args = ["jinja2", template, "--includes", template_root]
+ echo_proc = subprocess.Popen(echo_args, stdout=subprocess.PIPE, shell=False)
+ jinja_proc = subprocess.Popen(
+ jinja_args,
+ stdin=echo_proc.stdout,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ shell=False,
+ )
+ assert jinja_proc.wait() == 0
+ assert jinja_proc.stderr.readlines() == []
+ assert jinja_proc.stdout.readlines() == [(title + "\n").encode()]