test_imports.py 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. # -*- coding: utf-8 -*-
  2. import pytest
  3. from jinja2 import DictLoader
  4. from jinja2 import Environment
  5. from jinja2.exceptions import TemplateNotFound
  6. from jinja2.exceptions import TemplatesNotFound
  7. from jinja2.exceptions import TemplateSyntaxError
  8. @pytest.fixture
  9. def test_env():
  10. env = Environment(
  11. loader=DictLoader(
  12. dict(
  13. module="{% macro test() %}[{{ foo }}|{{ bar }}]{% endmacro %}",
  14. header="[{{ foo }}|{{ 23 }}]",
  15. o_printer="({{ o }})",
  16. )
  17. )
  18. )
  19. env.globals["bar"] = 23
  20. return env
  21. class TestImports(object):
  22. def test_context_imports(self, test_env):
  23. t = test_env.from_string('{% import "module" as m %}{{ m.test() }}')
  24. assert t.render(foo=42) == "[|23]"
  25. t = test_env.from_string(
  26. '{% import "module" as m without context %}{{ m.test() }}'
  27. )
  28. assert t.render(foo=42) == "[|23]"
  29. t = test_env.from_string(
  30. '{% import "module" as m with context %}{{ m.test() }}'
  31. )
  32. assert t.render(foo=42) == "[42|23]"
  33. t = test_env.from_string('{% from "module" import test %}{{ test() }}')
  34. assert t.render(foo=42) == "[|23]"
  35. t = test_env.from_string(
  36. '{% from "module" import test without context %}{{ test() }}'
  37. )
  38. assert t.render(foo=42) == "[|23]"
  39. t = test_env.from_string(
  40. '{% from "module" import test with context %}{{ test() }}'
  41. )
  42. assert t.render(foo=42) == "[42|23]"
  43. def test_import_needs_name(self, test_env):
  44. test_env.from_string('{% from "foo" import bar %}')
  45. test_env.from_string('{% from "foo" import bar, baz %}')
  46. with pytest.raises(TemplateSyntaxError):
  47. test_env.from_string('{% from "foo" import %}')
  48. def test_no_trailing_comma(self, test_env):
  49. with pytest.raises(TemplateSyntaxError):
  50. test_env.from_string('{% from "foo" import bar, %}')
  51. with pytest.raises(TemplateSyntaxError):
  52. test_env.from_string('{% from "foo" import bar,, %}')
  53. with pytest.raises(TemplateSyntaxError):
  54. test_env.from_string('{% from "foo" import, %}')
  55. def test_trailing_comma_with_context(self, test_env):
  56. test_env.from_string('{% from "foo" import bar, baz with context %}')
  57. test_env.from_string('{% from "foo" import bar, baz, with context %}')
  58. test_env.from_string('{% from "foo" import bar, with context %}')
  59. test_env.from_string('{% from "foo" import bar, with, context %}')
  60. test_env.from_string('{% from "foo" import bar, with with context %}')
  61. with pytest.raises(TemplateSyntaxError):
  62. test_env.from_string('{% from "foo" import bar,, with context %}')
  63. with pytest.raises(TemplateSyntaxError):
  64. test_env.from_string('{% from "foo" import bar with context, %}')
  65. def test_exports(self, test_env):
  66. m = test_env.from_string(
  67. """
  68. {% macro toplevel() %}...{% endmacro %}
  69. {% macro __private() %}...{% endmacro %}
  70. {% set variable = 42 %}
  71. {% for item in [1] %}
  72. {% macro notthere() %}{% endmacro %}
  73. {% endfor %}
  74. """
  75. ).module
  76. assert m.toplevel() == "..."
  77. assert not hasattr(m, "__missing")
  78. assert m.variable == 42
  79. assert not hasattr(m, "notthere")
  80. class TestIncludes(object):
  81. def test_context_include(self, test_env):
  82. t = test_env.from_string('{% include "header" %}')
  83. assert t.render(foo=42) == "[42|23]"
  84. t = test_env.from_string('{% include "header" with context %}')
  85. assert t.render(foo=42) == "[42|23]"
  86. t = test_env.from_string('{% include "header" without context %}')
  87. assert t.render(foo=42) == "[|23]"
  88. def test_choice_includes(self, test_env):
  89. t = test_env.from_string('{% include ["missing", "header"] %}')
  90. assert t.render(foo=42) == "[42|23]"
  91. t = test_env.from_string('{% include ["missing", "missing2"] ignore missing %}')
  92. assert t.render(foo=42) == ""
  93. t = test_env.from_string('{% include ["missing", "missing2"] %}')
  94. pytest.raises(TemplateNotFound, t.render)
  95. with pytest.raises(TemplatesNotFound) as e:
  96. t.render()
  97. assert e.value.templates == ["missing", "missing2"]
  98. assert e.value.name == "missing2"
  99. def test_includes(t, **ctx):
  100. ctx["foo"] = 42
  101. assert t.render(ctx) == "[42|23]"
  102. t = test_env.from_string('{% include ["missing", "header"] %}')
  103. test_includes(t)
  104. t = test_env.from_string("{% include x %}")
  105. test_includes(t, x=["missing", "header"])
  106. t = test_env.from_string('{% include [x, "header"] %}')
  107. test_includes(t, x="missing")
  108. t = test_env.from_string("{% include x %}")
  109. test_includes(t, x="header")
  110. t = test_env.from_string("{% include [x] %}")
  111. test_includes(t, x="header")
  112. def test_include_ignoring_missing(self, test_env):
  113. t = test_env.from_string('{% include "missing" %}')
  114. pytest.raises(TemplateNotFound, t.render)
  115. for extra in "", "with context", "without context":
  116. t = test_env.from_string(
  117. '{% include "missing" ignore missing ' + extra + " %}"
  118. )
  119. assert t.render() == ""
  120. def test_context_include_with_overrides(self, test_env):
  121. env = Environment(
  122. loader=DictLoader(
  123. dict(
  124. main="{% for item in [1, 2, 3] %}{% include 'item' %}{% endfor %}",
  125. item="{{ item }}",
  126. )
  127. )
  128. )
  129. assert env.get_template("main").render() == "123"
  130. def test_unoptimized_scopes(self, test_env):
  131. t = test_env.from_string(
  132. """
  133. {% macro outer(o) %}
  134. {% macro inner() %}
  135. {% include "o_printer" %}
  136. {% endmacro %}
  137. {{ inner() }}
  138. {% endmacro %}
  139. {{ outer("FOO") }}
  140. """
  141. )
  142. assert t.render().strip() == "(FOO)"
  143. def test_import_from_with_context(self):
  144. env = Environment(
  145. loader=DictLoader({"a": "{% macro x() %}{{ foobar }}{% endmacro %}"})
  146. )
  147. t = env.from_string(
  148. "{% set foobar = 42 %}{% from 'a' import x with context %}{{ x() }}"
  149. )
  150. assert t.render() == "42"