c1a6ff8ed007cf5dc5710ccc76b4b4c070b0a2c5
[jinja2.git] / jinja2 / testsuite / loader.py
1 # -*- coding: utf-8 -*-
2 """
3     jinja2.testsuite.loader
4     ~~~~~~~~~~~~~~~~~~~~~~~
5
6     Test the loaders.
7
8     :copyright: (c) 2010 by the Jinja Team.
9     :license: BSD, see LICENSE for more details.
10 """
11 import os
12 import sys
13 import tempfile
14 import shutil
15 import unittest
16
17 from jinja2.testsuite import JinjaTestCase, dict_loader, \
18      package_loader, filesystem_loader, function_loader, \
19      choice_loader, prefix_loader
20
21 from jinja2 import Environment, loaders
22 from jinja2.loaders import split_template_path
23 from jinja2.exceptions import TemplateNotFound
24
25
26 class LoaderTestCase(JinjaTestCase):
27
28     def test_dict_loader(self):
29         env = Environment(loader=dict_loader)
30         tmpl = env.get_template('justdict.html')
31         assert tmpl.render().strip() == 'FOO'
32         self.assert_raises(TemplateNotFound, env.get_template, 'missing.html')
33
34     def test_package_loader(self):
35         env = Environment(loader=package_loader)
36         tmpl = env.get_template('test.html')
37         assert tmpl.render().strip() == 'BAR'
38         self.assert_raises(TemplateNotFound, env.get_template, 'missing.html')
39
40     def test_filesystem_loader(self):
41         env = Environment(loader=filesystem_loader)
42         tmpl = env.get_template('test.html')
43         assert tmpl.render().strip() == 'BAR'
44         tmpl = env.get_template('foo/test.html')
45         assert tmpl.render().strip() == 'FOO'
46         self.assert_raises(TemplateNotFound, env.get_template, 'missing.html')
47
48     def test_choice_loader(self):
49         env = Environment(loader=choice_loader)
50         tmpl = env.get_template('justdict.html')
51         assert tmpl.render().strip() == 'FOO'
52         tmpl = env.get_template('test.html')
53         assert tmpl.render().strip() == 'BAR'
54         self.assert_raises(TemplateNotFound, env.get_template, 'missing.html')
55
56     def test_function_loader(self):
57         env = Environment(loader=function_loader)
58         tmpl = env.get_template('justfunction.html')
59         assert tmpl.render().strip() == 'FOO'
60         self.assert_raises(TemplateNotFound, env.get_template, 'missing.html')
61
62     def test_prefix_loader(self):
63         env = Environment(loader=prefix_loader)
64         tmpl = env.get_template('a/test.html')
65         assert tmpl.render().strip() == 'BAR'
66         tmpl = env.get_template('b/justdict.html')
67         assert tmpl.render().strip() == 'FOO'
68         self.assert_raises(TemplateNotFound, env.get_template, 'missing')
69
70     def test_caching(self):
71         changed = False
72         class TestLoader(loaders.BaseLoader):
73             def get_source(self, environment, template):
74                 return 'foo', None, lambda: not changed
75         env = Environment(loader=TestLoader(), cache_size=-1)
76         tmpl = env.get_template('template')
77         assert tmpl is env.get_template('template')
78         changed = True
79         assert tmpl is not env.get_template('template')
80         changed = False
81
82         env = Environment(loader=TestLoader(), cache_size=0)
83         assert env.get_template('template') \
84                is not env.get_template('template')
85
86         env = Environment(loader=TestLoader(), cache_size=2)
87         t1 = env.get_template('one')
88         t2 = env.get_template('two')
89         assert t2 is env.get_template('two')
90         assert t1 is env.get_template('one')
91         t3 = env.get_template('three')
92         assert 'one' in env.cache
93         assert 'two' not in env.cache
94         assert 'three' in env.cache
95
96     def test_split_template_path(self):
97         assert split_template_path('foo/bar') == ['foo', 'bar']
98         assert split_template_path('./foo/bar') == ['foo', 'bar']
99         self.assert_raises(TemplateNotFound, split_template_path, '../foo')
100
101
102 class ModuleLoaderTestCase(JinjaTestCase):
103     archive = None
104
105     def compile_down(self, zip='deflated', py_compile=False):
106         super(ModuleLoaderTestCase, self).setup()
107         log = []
108         self.reg_env = Environment(loader=prefix_loader)
109         if zip is not None:
110             self.archive = tempfile.mkstemp(suffix='.zip')[1]
111         else:
112             self.archive = tempfile.mkdtemp()
113         self.reg_env.compile_templates(self.archive, zip=zip,
114                                        log_function=log.append,
115                                        py_compile=py_compile)
116         self.mod_env = Environment(loader=loaders.ModuleLoader(self.archive))
117         return ''.join(log)
118
119     def teardown(self):
120         super(ModuleLoaderTestCase, self).teardown()
121         if hasattr(self, 'mod_env'):
122             if os.path.isfile(self.archive):
123                 os.remove(self.archive)
124             else:
125                 shutil.rmtree(self.archive)
126             self.archive = None
127
128     def test_log(self):
129         log = self.compile_down()
130         assert 'Compiled "a/foo/test.html" as ' \
131                'tmpl_a790caf9d669e39ea4d280d597ec891c4ef0404a' in log
132         assert 'Finished compiling templates' in log
133         assert 'Could not compile "a/syntaxerror.html": ' \
134                'Encountered unknown tag \'endif\'' in log
135
136     def _test_common(self):
137         tmpl1 = self.reg_env.get_template('a/test.html')
138         tmpl2 = self.mod_env.get_template('a/test.html')
139         assert tmpl1.render() == tmpl2.render()
140
141         tmpl1 = self.reg_env.get_template('b/justdict.html')
142         tmpl2 = self.mod_env.get_template('b/justdict.html')
143         assert tmpl1.render() == tmpl2.render()
144
145     def test_deflated_zip_compile(self):
146         self.compile_down(zip='deflated')
147         self._test_common()
148
149     def test_stored_zip_compile(self):
150         self.compile_down(zip='stored')
151         self._test_common()
152
153     def test_filesystem_compile(self):
154         self.compile_down(zip=None)
155         self._test_common()
156
157     def test_weak_references(self):
158         self.compile_down()
159         tmpl = self.mod_env.get_template('a/test.html')
160         key = loaders.ModuleLoader.get_template_key('a/test.html')
161         name = self.mod_env.loader.module.__name__
162
163         assert hasattr(self.mod_env.loader.module, key)
164         assert name in sys.modules
165
166         # unset all, ensure the module is gone from sys.modules
167         self.mod_env = tmpl = None
168
169         try:
170             import gc
171             gc.collect()
172         except:
173             pass
174
175         assert name not in sys.modules
176
177     def test_byte_compilation(self):
178         log = self.compile_down(py_compile=True)
179         assert 'Byte-compiled "a/test.html"' in log
180         tmpl1 = self.mod_env.get_template('a/test.html')
181         mod = self.mod_env.loader.module. \
182             tmpl_3c4ddf650c1a73df961a6d3d2ce2752f1b8fd490
183         assert mod.__file__.endswith('.pyc')
184
185     def test_choice_loader(self):
186         log = self.compile_down(py_compile=True)
187         assert 'Byte-compiled "a/test.html"' in log
188
189         self.mod_env.loader = loaders.ChoiceLoader([
190             self.mod_env.loader,
191             loaders.DictLoader({'DICT_SOURCE': 'DICT_TEMPLATE'})
192         ])
193
194         tmpl1 = self.mod_env.get_template('a/test.html')
195         self.assert_equal(tmpl1.render(), 'BAR')
196         tmpl2 = self.mod_env.get_template('DICT_SOURCE')
197         self.assert_equal(tmpl2.render(), 'DICT_TEMPLATE')
198
199     def test_prefix_loader(self):
200         log = self.compile_down(py_compile=True)
201         assert 'Byte-compiled "a/test.html"' in log
202
203         self.mod_env.loader = loaders.PrefixLoader({
204             'MOD':      self.mod_env.loader,
205             'DICT':     loaders.DictLoader({'test.html': 'DICT_TEMPLATE'})
206         })
207
208         tmpl1 = self.mod_env.get_template('MOD/a/test.html')
209         self.assert_equal(tmpl1.render(), 'BAR')
210         tmpl2 = self.mod_env.get_template('DICT/test.html')
211         self.assert_equal(tmpl2.render(), 'DICT_TEMPLATE')
212
213
214 def suite():
215     suite = unittest.TestSuite()
216     suite.addTest(unittest.makeSuite(LoaderTestCase))
217     suite.addTest(unittest.makeSuite(ModuleLoaderTestCase))
218     return suite