loader.py 8.0 KB

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