blob: 8002789bfebdfb6d0dcc0099d415ffae5282bc3c [file] [log] [blame]
Armin Ronacher3da90312008-05-23 16:37:28 +02001# -*- coding: utf-8 -*-
2"""
3 unit test for some extensions
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5
6 :copyright: 2008 by Armin Ronacher.
7 :license: BSD, see LICENSE for more details.
8"""
Armin Ronacher3e3a9be2008-06-14 12:44:15 +02009import re
Armin Ronacher6df604e2008-05-23 22:18:38 +020010from jinja2 import Environment, nodes
Armin Ronacher3e3a9be2008-06-14 12:44:15 +020011from jinja2.ext import Extension, Token
Armin Ronacher6df604e2008-05-23 22:18:38 +020012
13
14importable_object = 23
15
16
Armin Ronacher3e3a9be2008-06-14 12:44:15 +020017_line_re = re.compile(r'(\r\n|\r|\n)')
18_gettext_re = re.compile(r'_\((([^)\\]*(?:\\.[^)\\]*)*))\)(?s)')
19
20
Armin Ronacher6df604e2008-05-23 22:18:38 +020021class TestExtension(Extension):
22 tags = set(['test'])
23 ext_attr = 42
24
25 def parse(self, parser):
26 return nodes.Output([self.call_method('_dump', [
27 nodes.EnvironmentAttribute('sandboxed'),
28 self.attr('ext_attr'),
29 nodes.ImportedName(__name__ + '.importable_object'),
30 nodes.ContextReference()
31 ])]).set_lineno(parser.stream.next().lineno)
32
33 def _dump(self, sandboxed, ext_attr, imported_object, context):
34 return '%s|%s|%s|%s' % (
35 sandboxed,
36 ext_attr,
37 imported_object,
38 context.blocks
39 )
Armin Ronacher3da90312008-05-23 16:37:28 +020040
41
Armin Ronacher3e3a9be2008-06-14 12:44:15 +020042class PreprocessorExtension(Extension):
43
44 def preprocess(self, source, name, filename=None):
45 return source.replace('[[TEST]]', '({{ foo }})')
46
47
48class StreamFilterExtension(Extension):
49
50 def filter_stream(self, stream):
51 for token in stream:
52 if token.type is 'data':
53 for t in self.interpolate(token):
54 yield t
55 else:
56 yield token
57
58 def count_lines(self, value):
59 return len(_line_re.findall(value))
60
61 def interpolate(self, token):
62 pos = 0
63 end = len(token.value)
64 lineno = token.lineno
65 while 1:
66 match = _gettext_re.search(token.value, pos)
67 if match is None:
68 break
69 value = token.value[pos:match.start()]
70 if value:
71 yield Token(lineno, 'data', value)
72 lineno += self.count_lines(token.value)
73 yield Token(lineno, 'variable_begin', None)
74 yield Token(lineno, 'name', 'gettext')
75 yield Token(lineno, 'lparen', None)
76 yield Token(lineno, 'string', match.group(1))
77 yield Token(lineno, 'rparen', None)
78 yield Token(lineno, 'variable_end', None)
79 pos = match.end()
80 if pos < end:
81 yield Token(lineno, 'data', token.value[pos:])
82
83
Armin Ronacher3da90312008-05-23 16:37:28 +020084def test_loop_controls():
85 env = Environment(extensions=['jinja2.ext.loopcontrols'])
86
87 tmpl = env.from_string('''
88 {%- for item in [1, 2, 3, 4] %}
89 {%- if item % 2 == 0 %}{% continue %}{% endif -%}
90 {{ item }}
91 {%- endfor %}''')
92 assert tmpl.render() == '13'
93
94 tmpl = env.from_string('''
95 {%- for item in [1, 2, 3, 4] %}
96 {%- if item > 2 %}{% break %}{% endif -%}
97 {{ item }}
98 {%- endfor %}''')
99 assert tmpl.render() == '12'
100
101
102def test_do():
103 env = Environment(extensions=['jinja2.ext.do'])
104 tmpl = env.from_string('''
105 {%- set items = [] %}
106 {%- for char in "foo" %}
107 {%- do items.append(loop.index0 ~ char) %}
108 {%- endfor %}{{ items|join(', ') }}''')
109 assert tmpl.render() == '0f, 1o, 2o'
Armin Ronacher6df604e2008-05-23 22:18:38 +0200110
111
112def test_extension_nodes():
113 env = Environment(extensions=[TestExtension])
114 tmpl = env.from_string('{% test %}')
115 assert tmpl.render() == 'False|42|23|{}'
Armin Ronacher9cf95912008-05-24 19:54:43 +0200116
117
118def test_identifier():
119 assert TestExtension.identifier == __name__ + '.TestExtension'
Armin Ronacher9f258ff2008-05-24 22:28:52 +0200120
121
122def test_rebinding():
123 original = Environment(extensions=[TestExtension])
124 overlay = original.overlay()
125 for env in original, overlay:
126 for ext in env.extensions.itervalues():
127 assert ext.environment is env
Armin Ronacher3e3a9be2008-06-14 12:44:15 +0200128
129
130def test_preprocessor_extension():
131 env = Environment(extensions=[PreprocessorExtension])
132 tmpl = env.from_string('{[[TEST]]}')
133 assert tmpl.render(foo=42) == '{(42)}'
134
135
136def test_streamfilter_extension():
137 env = Environment(extensions=[StreamFilterExtension])
138 env.globals['gettext'] = lambda x: x.title()
139 tmpl = env.from_string('Foo _(bar) Baz')
140 assert tmpl.render() == 'Foo Bar Baz'