123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205 |
- 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):
- t = test_env.from_string(
- '{% import "module" as m %}{{ m.test() }}', globals={"foo": 42}
- )
- assert t.render() == "[42|23]"
- t = test_env.from_string('{% import "module" as m %}{{ m.test() }}')
- assert t.render() == "[|23]"
- def test_import_with_globals_override(self, test_env):
- t = test_env.from_string(
- '{% set foo = 41 %}{% import "module" as m %}{{ m.test() }}',
- globals={"foo": 42},
- )
- assert t.render() == "[42|23]"
- def test_from_import_with_globals(self, test_env):
- t = test_env.from_string(
- '{% from "module" import test %}{{ test() }}',
- globals={"foo": 42},
- )
- assert t.render() == "[42|23]"
- 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"
|