def test_nonvolatile(self): env = Environment(extensions=["jinja.ext.autoescape"], autoescape=True) tmpl = env.from_string('{{ {"foo": "<test>"}|xmlattr|escape }}') assert tmpl.render() == ' foo="<test>"' tmpl = env.from_string('{% autoescape false %}{{ {"foo": "<test>"}' "|xmlattr|escape }}{% endautoescape %}") assert tmpl.render() == " foo="&lt;test&gt;""
def test_scoped_setting(self): env = Environment(extensions=["jinja.ext.autoescape"], autoescape=True) tmpl = env.from_string(""" {{ "<HelloWorld>" }} {% autoescape false %} {{ "<HelloWorld>" }} {% endautoescape %} {{ "<HelloWorld>" }} """) assert tmpl.render().split() == [ u"<HelloWorld>", u"<HelloWorld>", u"<HelloWorld>", ] env = Environment(extensions=["jinja.ext.autoescape"], autoescape=False) tmpl = env.from_string(""" {{ "<HelloWorld>" }} {% autoescape true %} {{ "<HelloWorld>" }} {% endautoescape %} {{ "<HelloWorld>" }} """) assert tmpl.render().split() == [ u"<HelloWorld>", u"<HelloWorld>", u"<HelloWorld>", ]
def test_lstrip_blocks_false_with_no_lstrip(self, env): # Test that + is a NOP (but does not cause an error) if lstrip_blocks=False env = Environment(lstrip_blocks=False, trim_blocks=False) tmpl = env.from_string(""" {% if True %}\n {% endif %}""") assert tmpl.render() == " \n " tmpl = env.from_string(""" {%+ if True %}\n {%+ endif %}""") assert tmpl.render() == " \n "
def test_replace(self, env): env = Environment() tmpl = env.from_string('{{ string|replace("o", 42) }}') assert tmpl.render(string="<foo>") == "<f4242>" env = Environment(autoescape=True) tmpl = env.from_string('{{ string|replace("o", 42) }}') assert tmpl.render(string="<foo>") == "<f4242>" tmpl = env.from_string('{{ string|replace("<", 42) }}') assert tmpl.render(string="<foo>") == "42foo>" tmpl = env.from_string('{{ string|replace("o", ">x<") }}') assert tmpl.render(string=Markup("foo")) == "f>x<>x<"
def test_overlay_scopes(self): class MagicScopeExtension(Extension): tags = set(["overlay"]) def parse(self, parser): node = nodes.OverlayScope(lineno=next(parser.stream).lineno) node.body = list( parser.parse_statements(("name:endoverlay", ), drop_needle=True)) node.context = self.call_method("get_scope") return node def get_scope(self): return {"x": [1, 2, 3]} env = Environment(extensions=[MagicScopeExtension]) tmpl = env.from_string(""" {{- x }}|{% set z = 99 %} {%- overlay %} {{- y }}|{{ z }}|{% for item in x %}[{{ item }}]{% endfor %} {%- endoverlay %}| {{- x -}} """) assert tmpl.render(x=42, y=23) == "42|23|99|[1][2][3]|42"
def test_basic_scope_behavior(self): # This is what the old with statement compiled down to class ScopeExt(Extension): tags = set(["scope"]) def parse(self, parser): node = nodes.Scope(lineno=next(parser.stream).lineno) assignments = [] while parser.stream.current.type != "block_end": lineno = parser.stream.current.lineno if assignments: parser.stream.expect("comma") target = parser.parse_assign_target() parser.stream.expect("assign") expr = parser.parse_expression() assignments.append( nodes.Assign(target, expr, lineno=lineno)) node.body = assignments + list( parser.parse_statements( ("name:endscope", ), drop_needle=True)) return node env = Environment(extensions=[ScopeExt]) tmpl = env.from_string("""\ {%- scope a=1, b=2, c=b, d=e, e=5 -%} {{ a }}|{{ b }}|{{ c }}|{{ d }}|{{ e }} {%- endscope -%} """) assert tmpl.render(b=3, e=4) == "1|2|2|4|5"
def test_raw3(self, env): # The second newline after baz exists because it is AFTER the # {% raw %} and is ignored. env = Environment(lstrip_blocks=True, trim_blocks=True) tmpl = env.from_string( "bar\n{% raw %}\n {{baz}}2 spaces\n{% endraw %}\nfoo") assert tmpl.render(baz="test") == "bar\n\n {{baz}}2 spaces\nfoo"
def test_debug(self): env = Environment(extensions=["jinja.ext.debug"]) t = env.from_string("Hello\n{% debug %}\nGoodbye") out = t.render() for value in ("context", "cycler", "filters", "abs", "tests", "!="): assert "'{}'".format(value) in out
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"
def test_loop_controls(self): env = Environment(extensions=["jinja.ext.loopcontrols"]) tmpl = env.from_string(""" {%- for item in [1, 2, 3, 4] %} {%- if item % 2 == 0 %}{% continue %}{% endif -%} {{ item }} {%- endfor %}""") assert tmpl.render() == "13" tmpl = env.from_string(""" {%- for item in [1, 2, 3, 4] %} {%- if item > 2 %}{% break %}{% endif -%} {{ item }} {%- endfor %}""") assert tmpl.render() == "12"
def test_raw4(self, env): # The trailing dash of the {% raw -%} cleans both the spaces and # newlines up to the first character of data. env = Environment(lstrip_blocks=True, trim_blocks=False) tmpl = env.from_string( "bar\n{%- raw -%}\n\n \n 2 spaces\n space{%- endraw -%}\nfoo") assert tmpl.render() == "bar2 spaces\n spacefoo"
def test_do(self): env = Environment(extensions=["jinja.ext.do"]) tmpl = env.from_string(""" {%- set items = [] %} {%- for char in "foo" %} {%- do items.append(loop.index0 ~ char) %} {%- endfor %}{{ items|join(', ') }}""") assert tmpl.render() == "0f, 1o, 2o"
def test_comment_syntax(self, env): env = Environment("<!--", "-->", "${", "}", "<!--#", "-->") tmpl = env.from_string("""\ <!--# I'm a comment, I'm not interesting -->\ <!-- for item in seq ---> ${item} <!--- endfor -->""") assert tmpl.render(seq=list(range(5))) == "01234"
def test_erb_syntax(self, env): env = Environment("<%", "%>", "<%=", "%>", "<%#", "%>") tmpl = env.from_string("""\ <%# I'm a comment, I'm not interesting %>\ <% for item in seq -%> <%= item %> <%- endfor %>""") assert tmpl.render(seq=list(range(5))) == "01234"
def test_php_syntax(self, env): env = Environment("<?", "?>", "<?=", "?>", "<!--", "-->") tmpl = env.from_string("""\ <!-- I'm a comment, I'm not interesting -->\ <? for item in seq -?> <?= item ?> <?- endfor ?>""") assert tmpl.render(seq=list(range(5))) == "01234"
def test_urlize_rel_policy(self): env = Environment() env.policies["urlize.rel"] = None tmpl = env.from_string( '{{ "foo http://www.example.com/ bar"|urlize }}') assert tmpl.render() == ( 'foo <a href="http://www.example.com/">http://www.example.com/</a> bar' )
def test_include(self, env_trim): env_trim = Environment( loader=DictLoader( {"include": "{% macro test(foo) %}[{{ foo }}]{% endmacro %}"} ) ) tmpl = env_trim.from_string('{% from "include" import test %}{{ test("foo") }}') assert tmpl.render() == "[foo]"
def test_join(self, env): tmpl = env.from_string('{{ [1, 2, 3]|join("|") }}') out = tmpl.render() assert out == "1|2|3" env2 = Environment(autoescape=True) tmpl = env2.from_string( '{{ ["<foo>", "<span>foo</span>"|safe]|join }}') assert tmpl.render() == "<foo><span>foo</span>"
def test_no_variable_block(): env = Environment('{%', '%}', None, None) tmpl = env.from_string(NO_VARIABLE_BLOCK) assert tmpl.render(foo=42, seq=range(2)).splitlines() == [ '42', '01', 'foo is 42', '42 foos' ]
def test_super_in_scoped_block(self, env): env = Environment(loader=DictLoader({ "master.html": "{% for item in seq %}[{% block item scoped %}" "{{ item }}{% endblock %}]{% endfor %}" })) t = env.from_string('{% extends "master.html" %}{% block item %}' "{{ super() }}|{{ item * 2 }}{% endblock %}") assert t.render(seq=list(range(5))) == "[0|0][1|2][2|4][3|6][4|8]"
def test_line_syntax_priority(self, env): # XXX: why is the whitespace there in front of the newline? env = Environment("{%", "%}", "${", "}", "/*", "*/", "##", "#") tmpl = env.from_string("""\ /* ignore me. I'm a multiline comment */ ## for item in seq: * ${item} # this is just extra stuff ## endfor""") assert tmpl.render(seq=[1, 2]).strip() == "* 1\n* 2" env = Environment("{%", "%}", "${", "}", "/*", "*/", "#", "##") tmpl = env.from_string("""\ /* ignore me. I'm a multiline comment */ # for item in seq: * ${item} ## this is just extra stuff ## extra stuff i just want to ignore # endfor""") assert tmpl.render(seq=[1, 2]).strip() == "* 1\n\n* 2"
def test_extends_output_bugs(self, env): env = Environment(loader=DictLoader( {"parent.html": "(({% block title %}{% endblock %}))"})) t = env.from_string( '{% if expr %}{% extends "parent.html" %}{% endif %}' "[[{% block title %}title{% endblock %}]]" "{% for item in [1, 2, 3] %}({{ item }}){% endfor %}") assert t.render(expr=False) == "[[title]](1)(2)(3)" assert t.render(expr=True) == "((title))"
def test_scoped_block(self, env): env = Environment(loader=DictLoader({ "master.html": "{% for item in seq %}[{% block item scoped %}" "{% endblock %}]{% endfor %}" })) t = env.from_string( "{% extends 'master.html' %}{% block item %}{{ item }}{% endblock %}" ) assert t.render(seq=list(range(5))) == "[0][1][2][3][4]"
def test_attribute_map(self, env): User = namedtuple("User", "name") env = Environment() users = [ User("john"), User("jane"), User("mike"), ] tmpl = env.from_string('{{ users|map(attribute="name")|join("|") }}') assert tmpl.render(users=users) == "john|jane|mike"
def test_callable_defaults(self): env = Environment() env.globals["get_int"] = lambda: 42 t = env.from_string(""" {% macro test(a, b, c=get_int()) -%} {{ a + b + c }} {%- endmacro %} {{ test(1, 2) }}|{{ test(1, 2, 3) }} """) assert t.render().strip() == "45|6"
def test_comments(self, env): env = Environment("<!--", "-->", "{", "}") tmpl = env.from_string("""\ <ul> <!--- for item in seq --> <li>{item}</li> <!--- endfor --> </ul>""") assert tmpl.render(seq=list(range(3))) == ( "<ul>\n <li>0</li>\n <li>1</li>\n <li>2</li>\n</ul>")
def test_line_syntax(self, env): env = Environment("<%", "%>", "${", "}", "<%#", "%>", "%") tmpl = env.from_string("""\ <%# regular comment %> % for item in seq: ${item} % endfor""") assert [ int(x.strip()) for x in tmpl.render(seq=list(range(5))).split() ] == list(range(5)) env = Environment("<%", "%>", "${", "}", "<%#", "%>", "%", "##") tmpl = env.from_string("""\ <%# regular comment %> % for item in seq: ${item} ## the rest of the stuff % endfor""") assert [ int(x.strip()) for x in tmpl.render(seq=list(range(5))).split() ] == list(range(5))
def test_ascii_str(): @contextfilter def assert_func(context, value): assert type(value) is context["expected_type"] env = Environment() env.filters["assert"] = assert_func env.policies["compiler.ascii_str"] = False t = env.from_string('{{ "foo"|assert }}') t.render(expected_type=text_type) env.policies["compiler.ascii_str"] = True t = env.from_string('{{ "foo"|assert }}') t.render(expected_type=str) for val in True, False: env.policies["compiler.ascii_str"] = val t = env.from_string(u'{{ "\N{SNOWMAN}"|assert }}') t.render(expected_type=text_type)
def test_simple_reject_attr(self, env): User = namedtuple("User", "name,is_active") env = Environment() users = [ User("john", True), User("jane", True), User("mike", False), ] tmpl = env.from_string( '{{ users|rejectattr("is_active")|map(attribute="name")|join("|") }}' ) assert tmpl.render(users=users) == "mike"
def test_func_reject_attr(self, env): User = namedtuple("User", "id,name") env = Environment() users = [ User(1, "john"), User(2, "jane"), User(3, "mike"), ] tmpl = env.from_string( '{{ users|rejectattr("id", "odd")|map(attribute="name")|join("|") }}' ) assert tmpl.render(users=users) == "jane"
def test_autoescape_support(self): env = Environment( extensions=["jinja.ext.autoescape", "jinja.ext.i18n"]) env.install_gettext_callables( lambda x: u"<strong>Wert: %(name)s</strong>", lambda s, p, n: s, newstyle=True, ) t = env.from_string('{% autoescape ae %}{{ gettext("foo", name=' '"<test>") }}{% endautoescape %}') assert t.render(ae=True) == "<strong>Wert: <test></strong>" assert t.render(ae=False) == "<strong>Wert: <test></strong>"
def test_extends_position(): env = Environment(loader=DictLoader({ 'empty': '[{% block empty %}{% endblock %}]' })) tests = [ ('{% extends "empty" %}', '[!]'), (' {% extends "empty" %}', '[!]'), (' !\n', ' !\n!'), ('{# foo #} {% extends "empty" %}', '[!]'), ('{% set foo = "blub" %}{% extends "empty" %}', None) ] for tmpl, expected_output in tests: try: tmpl = env.from_string(tmpl + '{% block empty %}!{% endblock %}') except TemplateSyntaxError: assert expected_output is None, 'got syntax error' else: assert expected_output == tmpl.render()
def test_balancing(): from jinja import Environment env = Environment('{%', '%}', '${', '}') tmpl = env.from_string(BALANCING) assert tmpl.render(seq=range(3)) == "{'FOO': 0}{'FOO': 1}{'FOO': 2}"
def test_comment_syntax(): env = Environment('<!--', '-->', '${', '}', '<!--#', '-->') tmpl = env.from_string(COMMENT_SYNTAX) assert tmpl.render(seq=range(5)) == '01234'
def test_nonlocal_set(): env = Environment() env.globals['outer'] = 42 tmpl = env.from_string(NONLOCALSET) assert tmpl.render() == '9' assert env.globals['outer'] == 42
FULL_TEMPLATE = e.from_string('''\ <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <title>{{ title }} — Jinja Documentation</title> <meta http-equiv="content-type" content="text/html; charset=utf-8"> <link rel="stylesheet" href="style.css" type="text/css"> <style type="text/css"> {{ style|e }} </style> </head> <body> <div id="content"> {% if file_id == 'index' %} <div id="jinjalogo"></div> <h2 class="subheading plain">{{ title }}</h2> {% else %} <h1 class="heading"><span>Jinja</span></h1> <h2 class="subheading">{{ title }}</h2> {% endif %} {% if file_id != 'index' or toc %} <div id="toc"> <h2>Navigation</h2> <ul> <li><a href="index.html">back to index</a></li> </ul> {% if toc %} <h2>Contents</h2> <ul class="contents"> {% for key, value in toc %} <li><a href="{{ key }}">{{ value }}</a></li> {% endfor %} </ul> {% endif %} </div> {% endif %} <div id="contentwrapper"> {{ body }} </div> </div> </body> <!-- generated on: {{ generation_date }} file id: {{ file_id }} --> </html>\ ''')
def test_call(): from jinja import Environment env = Environment() env.globals['foo'] = lambda a, b, c, e, g: a + b + c + e + g tmpl = env.from_string(CALL) assert tmpl.render() == 'abdfh'
def test_factory(): def factory(context): return SimpleTranslator(context['LANGUAGE'] or 'en') env = Environment(translator_factory=factory) tmpl = env.from_string('{% trans "watch out" %}') assert tmpl.render(LANGUAGE='de') == 'pass auf'
def test_crazy_raw(): from jinja import Environment env = Environment('{', '}', '{', '}') tmpl = env.from_string('{raw}{broken foo}{endraw}') assert tmpl.render() == '{broken foo}'
def test_php_syntax(): env = Environment('<?', '?>', '<?=', '?>', '<!--', '-->') tmpl = env.from_string(PHP_SYNTAX) assert tmpl.render(seq=range(5)) == '01234'
def test_empty_super(): env = Environment(loader=DictLoader({'a': '{% block foo %}{% endblock %}'})) t = env.from_string('{% extends "a" %}{% block foo %}{{ super() }}{% endblock %}') assert t.render() == ''
def test_erb_syntax(): env = Environment('<%', '%>', '<%=', '%>', '<%#', '%>') tmpl = env.from_string(ERB_SYNTAX) assert tmpl.render(seq=range(5)) == '01234'
def test_comments(): from jinja import Environment env = Environment('<!--', '-->', '{', '}') tmpl = env.from_string(COMMENTS) assert tmpl.render(seq=range(3)) == ("<ul>\n <li>0</li>\n " "<li>1</li>\n <li>2</li>\n</ul>")
def test_smarty_syntax(): env = Environment('{', '}', '{', '}', '{*', '*}') tmpl = env.from_string(SMARTY_SYNTAX) assert tmpl.render(seq=range(5)) == '01234'
{% endblock %} {% endif %} """ class TestException(Exception): pass def throw_exception(): raise TestException() env = Environment( loader=DictLoader(dict(base=base_tmpl)) ) if __name__ == '__main__': for name in 'test1', 'test2': template_body = globals().get(name) template = env.from_string(template_body) try: print 'Rendering template:\n"""%s"""' % template_body template.render(throw_exception=throw_exception) except TestException: print 'Result: throw_exception() was called' else: print 'Result: throw_exception() was not called' print print 'First template illustrates that condition is working well' print 'The question is - why {% block %} is being evalueted '\ 'in false condition in second template?'