more thread safety in LRUCache
authorArmin Ronacher <armin.ronacher@active-4.com>
Mon, 19 May 2008 09:20:41 +0000 (11:20 +0200)
committerArmin Ronacher <armin.ronacher@active-4.com>
Mon, 19 May 2008 09:20:41 +0000 (11:20 +0200)
--HG--
branch : trunk

docs/templates.rst
jinja2/utils.py
tests/test_filters.py
tests/test_imports.py
tests/test_inheritance.py
tests/test_lrucache.py [new file with mode: 0644]
tests/test_various.py

index 935eff7fad5ebc72987c81cbb42f968be37a2a93..56c20f92ec90fcaa0d82887403a29b1e120d7b55 100644 (file)
@@ -1019,6 +1019,6 @@ do
 
 If the expression-statement extension is loaded a tag called `do` is available
 that works exactly like the regular variable expression (``{{ ... }}``) just
-that it doesn't print anything.  This can be used to modify lists:
+that it doesn't print anything.  This can be used to modify lists::
 
     {% do navigation.append('a string') %}
index 9d46639463791abdbd22ee7cb4fd3568c5837f4a..529abd2794ad1b018ee606be598a30b852a6e710 100644 (file)
@@ -465,12 +465,36 @@ class LRUCache(object):
         finally:
             self._wlock.release()
 
-    def __iter__(self):
-        """Iterate over all values in the cache dict, ordered by
+    def items(self):
+        """Return a list of items."""
+        result = [(key, self._mapping[key]) for key in list(self._queue)]
+        result.reverse()
+        return result
+
+    def iteritems(self):
+        """Iterate over all items."""
+        return iter(self.items())
+
+    def values(self):
+        """Return a list of all values."""
+        return [x[1] for x in self.items()]
+
+    def itervalue(self):
+        """Iterate over all values."""
+        return iter(self.values())
+
+    def keys(self):
+        """Return a list of all keys ordered by most recent usage."""
+        return list(self)
+
+    def iterkeys(self):
+        """Iterate over all keys in the cache dict, ordered by
         the most recent usage.
         """
         return reversed(tuple(self._queue))
 
+    __iter__ = iterkeys
+
     def __reversed__(self):
         """Iterate over the values in the cache dict, oldest items
         coming first.
index 824346e876a33a2cbefb4571100e20995ab67a00..659202775ecc1f2b737d2797d3145e2c50eb2563 100644 (file)
@@ -13,6 +13,7 @@
     :copyright: 2007 by Armin Ronacher.
     :license: BSD, see LICENSE for more details.
 """
+from jinja2 import Markup
 
 CAPITALIZE = '''{{ "foo bar"|capitalize }}'''
 CENTER = '''{{ "foo"|center(9) }}'''
@@ -69,7 +70,6 @@ GROUPBY = '''{% for grouper, list in [{'foo': 1, 'bar': 2},
 FILTERTAG = '''{% filter upper|replace('FOO', 'foo') %}foobar{% endfilter %}'''
 
 
-
 def test_capitalize(env):
     tmpl = env.from_string(CAPITALIZE)
     assert tmpl.render() == 'Foo bar'
@@ -291,3 +291,13 @@ def test_groupby(env):
 def test_filtertag(env):
     tmpl = env.from_string(FILTERTAG)
     assert tmpl.render() == 'fooBAR'
+
+
+def test_replace(env):
+    tmpl = env.from_string('{{ "foo"|replace("o", 42)}}')
+    assert tmpl.render() == 'f4242'
+
+
+def test_forceescape(env):
+    tmpl = env.from_string('{{ x|forceescape }}')
+    assert tmpl.render(x=Markup('<div />')) == u'&lt;div /&gt;'
index 92495e574c8eb02c2203f0a4384e5c5123a943af..2afab2e9d7c1dcec73db0da7b3901d024f581c5d 100644 (file)
@@ -46,3 +46,18 @@ def test_trailing_comma():
     test_env.from_string('{% from "foo" import bar, with context %}')
     test_env.from_string('{% from "foo" import bar, with, context %}')
     test_env.from_string('{% from "foo" import bar, with with context %}')
+
+
+def test_exports():
+    m = test_env.from_string('''
+        {% macro toplevel() %}...{% endmacro %}
+        {% macro __private() %}...{% endmacro %}
+        {% set variable = 42 %}
+        {% for item in [1] %}
+            {% macro notthere() %}{% endmacro %}
+        {% endfor %}
+    ''').module
+    assert m.toplevel() == '...'
+    assert not hasattr(m, '__missing')
+    assert m.variable == 42
+    assert not hasattr(m, 'notthere')
index 34e573803aa73e2294df7ac44a230909183a8b92..114ec9c431c19231b74e9c730a5e596ef1dd36b9 100644 (file)
@@ -93,3 +93,8 @@ def test_super():
 
 def test_working(env):
     tmpl = env.get_template('working')
+
+
+def test_reuse_blocks(env):
+    tmpl = env.from_string('{{ self.foo() }}|{% block foo %}42{% endblock %}|{{ self.foo() }}')
+    assert tmpl.render() == '42|42|42'
diff --git a/tests/test_lrucache.py b/tests/test_lrucache.py
new file mode 100644 (file)
index 0000000..6617e5c
--- /dev/null
@@ -0,0 +1,25 @@
+# -*- coding: utf-8 -*-
+"""
+    Tests the LRUCache
+    ~~~~~~~~~~~~~~~~~~
+
+    This module tests the LRU Cache
+
+    :copyright: Copyright 2008 by Armin Ronacher.
+    :license: GNU GPL.
+"""
+import thread
+import time
+import random
+from jinja2.utils import LRUCache
+
+
+def test_simple():
+    d = LRUCache(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
index 9235a29629f282b04c4dacc3e729d60e466c41c8..e81dfc0173533d5e38319aada375630666f7c6a9 100644 (file)
@@ -30,18 +30,6 @@ def test_raw(env):
     assert tmpl.render() == '{{ FOO }} and {% BAR %}'
 
 
-def test_lru_cache():
-    from jinja2.utils import LRUCache
-    d = LRUCache(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
-
-
 def test_const(env):
     tmpl = env.from_string(CONST)
     assert tmpl.render() == 'True|False|None|True|False'