[svn] added more unittests for jinja
authorArmin Ronacher <armin.ronacher@active-4.com>
Tue, 20 Mar 2007 15:17:48 +0000 (16:17 +0100)
committerArmin Ronacher <armin.ronacher@active-4.com>
Tue, 20 Mar 2007 15:17:48 +0000 (16:17 +0100)
--HG--
branch : trunk

docs/src/loaders.txt
jinja/loaders.py
tests/loaderres/__init__.py [new file with mode: 0644]
tests/loaderres/templates/test.html [new file with mode: 0644]
tests/test_loaders.py [new file with mode: 0644]
tests/test_various.py [new file with mode: 0644]

index 4522c35b379bce67f0f979465173225bc228eebe..8fd6fe83ee0ac41176ff8f6d39a9ec19aa9c370b 100644 (file)
@@ -53,7 +53,7 @@ Note that you have to give it a higher priority in the MRO than the
 .. sourcecode:: python
 
     import codecs
-    from os.path import join, getmtime
+    from os.path import join, getmtime, exists
     from jinja.loaders import BaseLoaderCachedLoaderMixin
     from jinja.exceptions import TemplateNotFound
 
@@ -79,7 +79,12 @@ Note that you have to give it a higher priority in the MRO than the
                 f.close()
 
         def check_source_changed(self, environment, name):
-            return getmtime(join(self.path, name))
+            fn = join(self.path, name)
+            if exists(fn):
+                return getmtime(fn)
+            return 0
 
 You don't have to provide the `check_source_changed` method. If it doesn't
-exist the option `auto_reload` won't have an effect.
+exist the option `auto_reload` won't have an effect. Also note that the
+`check_source_changed` method must not raise an exception if the template
+does not exist but return ``0``.
index 76d476df5156b871526bf55e82d1e949a56b0879..6901b408e74b1725d23dbf4e03aeaeacfc032174 100644 (file)
@@ -25,7 +25,7 @@ except ImportError:
     resource_exists = resource_string = resource_filename = None
 
 
-__all__ = ['FileSystemLoader', 'PackageLoader', 'DictLoader']
+__all__ = ['FileSystemLoader', 'PackageLoader', 'DictLoader', 'ChoiceLoader']
 
 
 def get_template_filename(searchpath, name):
@@ -261,7 +261,10 @@ class FileSystemLoader(CachedLoaderMixin, BaseLoader):
             raise TemplateNotFound(name)
 
     def check_source_changed(self, environment, name):
-        return path.getmtime(get_template_filename(self.searchpath, name))
+        filename = get_template_filename(self.searchpath, name)
+        if path.exists(filename):
+            return path.getmtime(filename)
+        return 0
 
 
 class PackageLoader(CachedLoaderMixin, BaseLoader):
@@ -323,9 +326,11 @@ class PackageLoader(CachedLoaderMixin, BaseLoader):
         return contents.decode(environment.template_charset)
 
     def check_source_changed(self, environment, name):
-        name = '/'.join([self.package_path] + [p for p in name.split('/')
-                        if p and p[0] != '.'])
-        return path.getmtime(resource_filename(self.package_name, name))
+        fn = resource_filename(self.package_name, '/'.join([self.package_path] +
+                               [p for p in name.split('/') if p and p[0] != '.']))
+        if resource_exists(self.package_name, fn):
+            return path.getmtime(fn)
+        return 0
 
 
 class DictLoader(BaseLoader):
@@ -337,7 +342,7 @@ class DictLoader(BaseLoader):
         from jinja import Environment, DictLoader
         e = Environment(loader=DictLoader(dict(
             layout='...',
-            index='{% extends layout %}...'
+            index='{% extends 'layout' %}...'
         )))
     """
 
@@ -348,3 +353,44 @@ class DictLoader(BaseLoader):
         if name in self.templates:
             return self.templates[name]
         raise TemplateNotFound(name)
+
+
+class ChoiceLoader(object):
+    """
+    A loader that tries multiple loaders in the order they are given to
+    the `ChoiceLoader`:
+
+    .. sourcecode:: python
+
+        from jinja import ChoiceLoader, FileSystemLoader
+        loader1 = FileSystemLoader("templates1")
+        loader2 = FileSystemLoader("templates2")
+        loader = ChoiceLoader([loader1, loader2])
+    """
+
+    def __init__(self, loaders):
+        self.loaders = list(loaders)
+
+    def get_source(self, environment, name, parent):
+        for loader in self.loaders:
+            try:
+                return loader.get_source(environment, name, parent)
+            except TemplateNotFound:
+                continue
+        raise TemplateNotFound(name)
+
+    def parse(self, environment, name, parent):
+        for loader in self.loaders:
+            try:
+                return loader.parse(environment, name, parent)
+            except TemplateNotFound:
+                continue
+        raise TemplateNotFound(name)
+
+    def load(self, environment, name, translator):
+        for loader in self.loaders:
+            try:
+                return loader.load(environment, name, translator)
+            except TemplateNotFound:
+                continue
+        raise TemplateNotFound(name)
diff --git a/tests/loaderres/__init__.py b/tests/loaderres/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/loaderres/templates/test.html b/tests/loaderres/templates/test.html
new file mode 100644 (file)
index 0000000..ba578e4
--- /dev/null
@@ -0,0 +1 @@
+BAR
diff --git a/tests/test_loaders.py b/tests/test_loaders.py
new file mode 100644 (file)
index 0000000..fffec03
--- /dev/null
@@ -0,0 +1,72 @@
+# -*- coding: utf-8 -*-
+"""
+    unit test for the loaders
+    ~~~~~~~~~~~~~~~~~~~~~~~~~
+
+    :copyright: 2007 by Armin Ronacher.
+    :license: BSD, see LICENSE for more details.
+"""
+
+from jinja import Environment, loaders
+from jinja.exceptions import TemplateNotFound
+
+
+dict_loader = loaders.DictLoader({
+    'justdict.html':        'FOO'
+})
+
+package_loader = loaders.PackageLoader('loaderres', 'templates')
+
+filesystem_loader = loaders.FileSystemLoader('loaderres/templates')
+
+choice_loader = loaders.ChoiceLoader([dict_loader, package_loader])
+
+
+def test_dict_loader():
+    env = Environment(loader=dict_loader)
+    tmpl = env.get_template('justdict.html')
+    assert tmpl.render().strip() == 'FOO'
+    try:
+        env.get_template('missing.html')
+    except TemplateNotFound:
+        pass
+    else:
+        raise AssertionError('expected template exception')
+
+
+def test_package_loader():
+    env = Environment(loader=package_loader)
+    tmpl = env.get_template('test.html')
+    assert tmpl.render().strip() == 'BAR'
+    try:
+        env.get_template('missing.html')
+    except TemplateNotFound:
+        pass
+    else:
+        raise AssertionError('expected template exception')
+
+
+def test_filesystem_loader():
+    env = Environment(loader=filesystem_loader)
+    tmpl = env.get_template('test.html')
+    assert tmpl.render().strip() == 'BAR'
+    try:
+        env.get_template('missing.html')
+    except TemplateNotFound:
+        pass
+    else:
+        raise AssertionError('expected template exception')
+
+
+def test_choice_loader():
+    env = Environment(loader=choice_loader)
+    tmpl = env.get_template('justdict.html')
+    assert tmpl.render().strip() == 'FOO'
+    tmpl = env.get_template('test.html')
+    assert tmpl.render().strip() == 'BAR'
+    try:
+        env.get_template('missing.html')
+    except TemplateNotFound:
+        pass
+    else:
+        raise AssertionError('expected template exception')
diff --git a/tests/test_various.py b/tests/test_various.py
new file mode 100644 (file)
index 0000000..b7336e2
--- /dev/null
@@ -0,0 +1,61 @@
+# -*- coding: utf-8 -*-
+"""
+    unit test for various things
+    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+    :copyright: 2007 by Armin Ronacher.
+    :license: BSD, see LICENSE for more details.
+"""
+
+KEYWORDS = '''
+{{ with }}
+{{ as }}
+{{ import }}
+{{ from }}
+{{ class }}
+{{ def }}
+{{ try }}
+{{ except }}
+{{ exec }}
+{{ global }}
+{{ assert }}
+{{ break }}
+{{ continue }}
+{{ lambda }}
+{{ return }}
+{{ raise }}
+{{ yield }}
+{{ while }}
+{{ pass }}
+{{ finally }}
+'''
+
+UNPACKING = '''{% for a, b, c in [[1, 2, 3]] %}{{ a }}|{{ b }}|{{ c }}{% endfor %}'''
+
+RAW = '''{% raw %}{{ FOO }} and {% BAR %}{% endraw %}'''
+
+
+def test_keywords(env):
+    env.from_string(KEYWORDS)
+
+
+def test_unpacking(env):
+    tmpl = env.from_string(UNPACKING)
+    assert tmpl.render() == '1|2|3'
+
+
+def test_raw(env):
+    tmpl = env.from_string(RAW)
+    assert tmpl.render() == '{{ FOO }} and {% BAR %}'
+
+
+def test_cache_dict():
+    from jinja.utils import CacheDict
+    d = CacheDict(3)
+    d["a"] = 1
+    d["b"] = 2
+    d["c"] = 3
+    d["a"]
+    d["d"] = 4
+    assert len(d) == 3
+    assert 'a' in d and 'c' in d and 'd' in d and 'b' not in d