aboutsummaryrefslogtreecommitdiff
path: root/tests/test_imports.py
diff options
context:
space:
mode:
Diffstat (limited to 'tests/test_imports.py')
-rw-r--r--tests/test_imports.py223
1 files changed, 223 insertions, 0 deletions
diff --git a/tests/test_imports.py b/tests/test_imports.py
new file mode 100644
index 00000000..054c9010
--- /dev/null
+++ b/tests/test_imports.py
@@ -0,0 +1,223 @@
+import pytest
+
+from jinja2.environment import Environment
+from jinja2.exceptions import TemplateNotFound
+from jinja2.exceptions import TemplatesNotFound
+from jinja2.exceptions import TemplateSyntaxError
+from jinja2.exceptions import UndefinedError
+from jinja2.loaders import DictLoader
+
+
+@pytest.fixture
+def test_env():
+ env = Environment(
+ loader=DictLoader(
+ dict(
+ module="{% macro test() %}[{{ foo }}|{{ bar }}]{% endmacro %}",
+ header="[{{ foo }}|{{ 23 }}]",
+ o_printer="({{ o }})",
+ )
+ )
+ )
+ env.globals["bar"] = 23
+ return env
+
+
+class TestImports:
+ def test_context_imports(self, test_env):
+ t = test_env.from_string('{% import "module" as m %}{{ m.test() }}')
+ assert t.render(foo=42) == "[|23]"
+ t = test_env.from_string(
+ '{% import "module" as m without context %}{{ m.test() }}'
+ )
+ assert t.render(foo=42) == "[|23]"
+ t = test_env.from_string(
+ '{% import "module" as m with context %}{{ m.test() }}'
+ )
+ assert t.render(foo=42) == "[42|23]"
+ t = test_env.from_string('{% from "module" import test %}{{ test() }}')
+ assert t.render(foo=42) == "[|23]"
+ t = test_env.from_string(
+ '{% from "module" import test without context %}{{ test() }}'
+ )
+ assert t.render(foo=42) == "[|23]"
+ t = test_env.from_string(
+ '{% from "module" import test with context %}{{ test() }}'
+ )
+ assert t.render(foo=42) == "[42|23]"
+
+ def test_import_needs_name(self, test_env):
+ test_env.from_string('{% from "foo" import bar %}')
+ test_env.from_string('{% from "foo" import bar, baz %}')
+
+ with pytest.raises(TemplateSyntaxError):
+ test_env.from_string('{% from "foo" import %}')
+
+ def test_no_trailing_comma(self, test_env):
+ with pytest.raises(TemplateSyntaxError):
+ test_env.from_string('{% from "foo" import bar, %}')
+
+ with pytest.raises(TemplateSyntaxError):
+ test_env.from_string('{% from "foo" import bar,, %}')
+
+ with pytest.raises(TemplateSyntaxError):
+ test_env.from_string('{% from "foo" import, %}')
+
+ def test_trailing_comma_with_context(self, test_env):
+ test_env.from_string('{% from "foo" import bar, baz with context %}')
+ test_env.from_string('{% from "foo" import bar, baz, with context %}')
+ test_env.from_string('{% from "foo" import bar, with context %}')
+ test_env.from_string('{% from "foo" import bar, with, context %}')
+ test_env.from_string('{% from "foo" import bar, with with context %}')
+
+ with pytest.raises(TemplateSyntaxError):
+ test_env.from_string('{% from "foo" import bar,, with context %}')
+
+ with pytest.raises(TemplateSyntaxError):
+ test_env.from_string('{% from "foo" import bar with context, %}')
+
+ def test_exports(self, test_env):
+ m = test_env.from_string(
+ """
+ {% macro toplevel() %}...{% endmacro %}
+ {% macro __private() %}...{% endmacro %}
+ {% set variable = 42 %}
+ {% for item in [1] %}
+ {% macro notthere() %}{% endmacro %}
+ {% endfor %}
+ """
+ ).module
+ assert m.toplevel() == "..."
+ assert not hasattr(m, "__missing")
+ assert m.variable == 42
+ assert not hasattr(m, "notthere")
+
+ def test_not_exported(self, test_env):
+ t = test_env.from_string("{% from 'module' import nothing %}{{ nothing() }}")
+
+ with pytest.raises(UndefinedError, match="does not export the requested name"):
+ t.render()
+
+ def test_import_with_globals(self, test_env):
+ env = Environment(
+ loader=DictLoader(
+ {
+ "macros": "{% macro test() %}foo: {{ foo }}{% endmacro %}",
+ "test": "{% import 'macros' as m %}{{ m.test() }}",
+ "test1": "{% import 'macros' as m %}{{ m.test() }}",
+ }
+ )
+ )
+ tmpl = env.get_template("test", globals={"foo": "bar"})
+ assert tmpl.render() == "foo: bar"
+
+ tmpl = env.get_template("test1")
+ assert tmpl.render() == "foo: "
+
+ def test_import_with_globals_override(self, test_env):
+ env = Environment(
+ loader=DictLoader(
+ {
+ "macros": "{% set foo = '42' %}{% macro test() %}"
+ "foo: {{ foo }}{% endmacro %}",
+ "test": "{% from 'macros' import test %}{{ test() }}",
+ }
+ )
+ )
+ tmpl = env.get_template("test", globals={"foo": "bar"})
+ assert tmpl.render() == "foo: 42"
+
+ def test_from_import_with_globals(self, test_env):
+ env = Environment(
+ loader=DictLoader(
+ {
+ "macros": "{% macro testing() %}foo: {{ foo }}{% endmacro %}",
+ "test": "{% from 'macros' import testing %}{{ testing() }}",
+ }
+ )
+ )
+ tmpl = env.get_template("test", globals={"foo": "bar"})
+ assert tmpl.render() == "foo: bar"
+
+
+class TestIncludes:
+ def test_context_include(self, test_env):
+ t = test_env.from_string('{% include "header" %}')
+ assert t.render(foo=42) == "[42|23]"
+ t = test_env.from_string('{% include "header" with context %}')
+ assert t.render(foo=42) == "[42|23]"
+ t = test_env.from_string('{% include "header" without context %}')
+ assert t.render(foo=42) == "[|23]"
+
+ def test_choice_includes(self, test_env):
+ t = test_env.from_string('{% include ["missing", "header"] %}')
+ assert t.render(foo=42) == "[42|23]"
+
+ t = test_env.from_string('{% include ["missing", "missing2"] ignore missing %}')
+ assert t.render(foo=42) == ""
+
+ t = test_env.from_string('{% include ["missing", "missing2"] %}')
+ pytest.raises(TemplateNotFound, t.render)
+ with pytest.raises(TemplatesNotFound) as e:
+ t.render()
+
+ assert e.value.templates == ["missing", "missing2"]
+ assert e.value.name == "missing2"
+
+ def test_includes(t, **ctx):
+ ctx["foo"] = 42
+ assert t.render(ctx) == "[42|23]"
+
+ t = test_env.from_string('{% include ["missing", "header"] %}')
+ test_includes(t)
+ t = test_env.from_string("{% include x %}")
+ test_includes(t, x=["missing", "header"])
+ t = test_env.from_string('{% include [x, "header"] %}')
+ test_includes(t, x="missing")
+ t = test_env.from_string("{% include x %}")
+ test_includes(t, x="header")
+ t = test_env.from_string("{% include [x] %}")
+ test_includes(t, x="header")
+
+ def test_include_ignoring_missing(self, test_env):
+ t = test_env.from_string('{% include "missing" %}')
+ pytest.raises(TemplateNotFound, t.render)
+ for extra in "", "with context", "without context":
+ t = test_env.from_string(
+ '{% include "missing" ignore missing ' + extra + " %}"
+ )
+ assert t.render() == ""
+
+ def test_context_include_with_overrides(self, test_env):
+ env = Environment(
+ loader=DictLoader(
+ dict(
+ main="{% for item in [1, 2, 3] %}{% include 'item' %}{% endfor %}",
+ item="{{ item }}",
+ )
+ )
+ )
+ assert env.get_template("main").render() == "123"
+
+ def test_unoptimized_scopes(self, test_env):
+ t = test_env.from_string(
+ """
+ {% macro outer(o) %}
+ {% macro inner() %}
+ {% include "o_printer" %}
+ {% endmacro %}
+ {{ inner() }}
+ {% endmacro %}
+ {{ outer("FOO") }}
+ """
+ )
+ assert t.render().strip() == "(FOO)"
+
+ def test_import_from_with_context(self):
+ env = Environment(
+ loader=DictLoader({"a": "{% macro x() %}{{ foobar }}{% endmacro %}"})
+ )
+ t = env.from_string(
+ "{% set foobar = 42 %}{% from 'a' import x with context %}{{ x() }}"
+ )
+ assert t.render() == "42"