summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2012-07-07 21:13:48 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2012-07-07 21:13:48 -0400
commit03c97d16a8f83d58d629acd8173ce72d2e8dae37 (patch)
tree4f244a1733d703eaa052d8aff547e03795aac723
parent0f58ab39bf6753492e565a85f9f436d476a550b1 (diff)
downloadmako-03c97d16a8f83d58d629acd8173ce72d2e8dae37.tar.gz
- [bug] Can now use strict_undefined at the
same time args passed to def() are used by other elements of the <%def> tag. [ticket:191]
-rw-r--r--CHANGES5
-rw-r--r--mako/parsetree.py2
-rw-r--r--test/__init__.py58
-rw-r--r--test/test_cache.py56
-rw-r--r--test/test_def.py48
5 files changed, 127 insertions, 42 deletions
diff --git a/CHANGES b/CHANGES
index a6d0509..2863935 100644
--- a/CHANGES
+++ b/CHANGES
@@ -4,6 +4,11 @@
when no statements are otherwise present.
Courtesy Ben Trofatter [ticket:146]
+- [bug] Can now use strict_undefined at the
+ same time args passed to def() are used
+ by other elements of the <%def> tag.
+ [ticket:191]
+
0.7.0
- [feature] Added new "loop" variable to templates,
is provided within a % for block to provide
diff --git a/mako/parsetree.py b/mako/parsetree.py
index 9b488d3..ecd8242 100644
--- a/mako/parsetree.py
+++ b/mako/parsetree.py
@@ -445,6 +445,8 @@ class DefTag(Tag):
difference(filters.DEFAULT_ESCAPES.keys())
).union(
self.expression_undeclared_identifiers
+ ).difference(
+ self.function_decl.argnames
)
class BlockTag(Tag):
diff --git a/test/__init__.py b/test/__init__.py
index 7f258dd..0839312 100644
--- a/test/__init__.py
+++ b/test/__init__.py
@@ -3,7 +3,7 @@ import unittest, os
from mako.util import py3k
from mako.util import function_named
import re
-
+from mako.cache import CacheImpl, register_plugin
from nose import SkipTest
@@ -11,34 +11,34 @@ template_base = os.path.join(os.path.dirname(__file__), 'templates')
module_base = os.path.join(template_base, 'modules')
class TemplateTest(unittest.TestCase):
-
+
def _file_template(self, filename, **kw):
filepath = self._file_path(filename)
return Template(uri=filename, filename=filepath,
module_directory=module_base, **kw)
-
+
def _file_path(self, filename):
name, ext = os.path.splitext(filename)
-
+
if py3k:
py3k_path = os.path.join(template_base, name + "_py3k" + ext)
if os.path.exists(py3k_path):
return py3k_path
-
+
return os.path.join(template_base, filename)
-
- def _do_file_test(self, filename, expected, filters=None,
+
+ def _do_file_test(self, filename, expected, filters=None,
unicode_=True, template_args=None, **kw):
t1 = self._file_template(filename, **kw)
- self._do_test(t1, expected, filters=filters,
+ self._do_test(t1, expected, filters=filters,
unicode_=unicode_, template_args=template_args)
-
- def _do_memory_test(self, source, expected, filters=None,
+
+ def _do_memory_test(self, source, expected, filters=None,
unicode_=True, template_args=None, **kw):
t1 = Template(text=source, **kw)
- self._do_test(t1, expected, filters=filters,
+ self._do_test(t1, expected, filters=filters,
unicode_=unicode_, template_args=template_args)
-
+
def _do_test(self, template, expected, filters=None, template_args=None, unicode_=True):
if template_args is None:
template_args = {}
@@ -46,11 +46,11 @@ class TemplateTest(unittest.TestCase):
output = template.render_unicode(**template_args)
else:
output = template.render(**template_args)
-
+
if filters:
output = filters(output)
eq_(output, expected)
-
+
def eq_(a, b, msg=None):
"""Assert a == b, with repr messaging on failure."""
assert a == b, msg or "%r != %r" % (a, b)
@@ -65,7 +65,7 @@ def assert_raises(except_cls, callable_, *args, **kw):
success = False
except except_cls, e:
success = True
-
+
# assert outside the block so it works for AssertionError too !
assert success, "Callable did not raise an exception"
@@ -106,4 +106,30 @@ def requires_no_pygments(fn):
import pygments
except:
pygments = None
- return skip_if(lambda:pygments is not None)(fn) \ No newline at end of file
+ return skip_if(lambda: pygments is not None)(fn)
+
+class PlainCacheImpl(CacheImpl):
+ """Simple memory cache impl so that tests which
+ use caching can run without beaker. """
+
+ def __init__(self, cache):
+ self.cache = cache
+ self.data = {}
+
+ def get_or_create(self, key, creation_function, **kw):
+ if key in self.data:
+ return self.data[key]
+ else:
+ self.data[key] = data = creation_function(**kw)
+ return data
+
+ def put(self, key, value, **kw):
+ self.data[key] = value
+
+ def get(self, key, **kw):
+ return self.data[key]
+
+ def invalidate(self, key, **kw):
+ del self.data[key]
+
+register_plugin("plain", __name__, "PlainCacheImpl")
diff --git a/test/test_cache.py b/test/test_cache.py
index dc20b8f..bd8cf47 100644
--- a/test/test_cache.py
+++ b/test/test_cache.py
@@ -12,14 +12,17 @@ try:
except:
from nose import SkipTest
raise SkipTest("Beaker is required for these tests.")
-
+
from mako.cache import register_plugin, CacheImpl
class MockCacheImpl(CacheImpl):
realcacheimpl = None
+
def __init__(self, cache):
self.cache = cache
- use_beaker= self.cache.template.cache_args.get('use_beaker', True)
+ use_beaker = self.cache.\
+ template.cache_args.\
+ get('use_beaker', True)
if use_beaker:
self.realcacheimpl = cache._load_impl("beaker")
@@ -27,7 +30,8 @@ class MockCacheImpl(CacheImpl):
self.key = key
self.kwargs = kw.copy()
if self.realcacheimpl:
- return self.realcacheimpl.get_or_create(key, creation_function, **kw)
+ return self.realcacheimpl.\
+ get_or_create(key, creation_function, **kw)
else:
return creation_function()
@@ -36,13 +40,13 @@ class MockCacheImpl(CacheImpl):
self.kwargs = kw.copy()
if self.realcacheimpl:
self.realcacheimpl.put(key, value, **kw)
-
+
def get(self, key, **kw):
self.key = key
self.kwargs = kw.copy()
if self.realcacheimpl:
return self.realcacheimpl.get(key, **kw)
-
+
def invalidate(self, key, **kw):
self.key = key
self.kwargs = kw.copy()
@@ -104,7 +108,7 @@ class CacheTest(TemplateTest):
callcount[0] += 1
%>
</%def>
-
+
${foo()}
${foo()}
${foo()}
@@ -134,7 +138,7 @@ class CacheTest(TemplateTest):
m = self._install_mock_cache(t)
eq_(t.render().strip(), "callcount: [2]")
-
+
def test_nested_def(self):
t = Template("""
<%!
@@ -163,7 +167,7 @@ class CacheTest(TemplateTest):
'callcount: [1]',
]
assert m.kwargs == {}
-
+
def test_page(self):
t = Template("""
<%!
@@ -251,7 +255,7 @@ class CacheTest(TemplateTest):
assert result_lines(t.render()) == ['hi']
assert m.key == "foo_hi"
-
+
def test_dynamic_key_with_imports(self):
lookup = TemplateLookup()
lookup.put_string("foo.html", """
@@ -276,7 +280,7 @@ class CacheTest(TemplateTest):
"callcount: [1]"
]
assert m.kwargs == {}
-
+
def test_fileargs_implicit(self):
l = lookup.TemplateLookup(module_directory=module_base)
l.put_string("test","""
@@ -295,7 +299,7 @@ class CacheTest(TemplateTest):
${foo()}
callcount: ${callcount}
""")
-
+
m = self._install_mock_cache(l.get_template('test'))
assert result_lines(l.get_template('test').render()) == [
'this is foo',
@@ -304,7 +308,7 @@ class CacheTest(TemplateTest):
'callcount: [1]',
]
eq_(m.kwargs, {'type':'dbm'})
-
+
def test_fileargs_deftag(self):
t = Template("""
<%%!
@@ -369,7 +373,7 @@ class CacheTest(TemplateTest):
m = self._install_mock_cache(t)
t.render()
eq_(m.kwargs, {'dir':module_base, 'type':'file', 'timeout':30})
-
+
t2 = Template("""
<%%page cached="True" cache_timeout="30" cache_dir="%s" cache_type="file" cache_key='somekey'/>
hi
@@ -396,7 +400,7 @@ class CacheTest(TemplateTest):
${foo()}
callcount: ${callcount}
""")
-
+
t = l.get_template('test')
m = self._install_mock_cache(t)
assert result_lines(l.get_template('test').render()) == [
@@ -406,7 +410,7 @@ class CacheTest(TemplateTest):
'callcount: [1]',
]
eq_(m.kwargs, {'dir':module_base, 'type':'file'})
-
+
def test_buffered(self):
t = Template("""
<%!
@@ -420,11 +424,11 @@ class CacheTest(TemplateTest):
</%def>
""", buffer_filters=["a"])
assert result_lines(t.render()) == ["this is a this is a test", "this is a this is a test"]
-
+
def test_load_from_expired(self):
"""test that the cache callable can be called safely after the
originating template has completed rendering.
-
+
"""
t = Template("""
${foo()}
@@ -432,12 +436,12 @@ class CacheTest(TemplateTest):
foo
</%def>
""")
-
+
x1 = t.render()
time.sleep(3)
x2 = t.render()
assert x1.strip() == x2.strip() == "foo"
-
+
def test_cache_uses_current_context(self):
t = Template("""
${foo()}
@@ -445,7 +449,7 @@ class CacheTest(TemplateTest):
foo: ${x}
</%def>
""")
-
+
x1 = t.render(x=1)
time.sleep(3)
x2 = t.render(x=2)
@@ -496,10 +500,10 @@ class CacheTest(TemplateTest):
assert result_lines(t.render(x=3)) == ["foo: 3", "bar: 1"]
t.cache.invalidate_def('bar')
assert result_lines(t.render(x=4)) == ["foo: 3", "bar: 4"]
-
+
t = Template("""
<%%page cached="True" cache_type="dbm" cache_dir="%s"/>
-
+
page: ${x}
""" % module_base)
assert result_lines(t.render(x=1)) == ["page: 1"]
@@ -507,10 +511,10 @@ class CacheTest(TemplateTest):
t.cache.invalidate_body()
assert result_lines(t.render(x=3)) == ["page: 3"]
assert result_lines(t.render(x=4)) == ["page: 3"]
-
+
def test_custom_args_def(self):
t = Template("""
- <%def name="foo()" cached="True" cache_region="myregion"
+ <%def name="foo()" cached="True" cache_region="myregion"
cache_timeout="50" cache_foo="foob">
</%def>
${foo()}
@@ -521,7 +525,7 @@ class CacheTest(TemplateTest):
def test_custom_args_block(self):
t = Template("""
- <%block name="foo" cached="True" cache_region="myregion"
+ <%block name="foo" cached="True" cache_region="myregion"
cache_timeout="50" cache_foo="foob">
</%block>
""", cache_args={'use_beaker':False})
@@ -531,7 +535,7 @@ class CacheTest(TemplateTest):
def test_custom_args_page(self):
t = Template("""
- <%page cached="True" cache_region="myregion"
+ <%page cached="True" cache_region="myregion"
cache_timeout="50" cache_foo="foob"/>
""", cache_args={'use_beaker':False})
m = self._install_mock_cache(t)
diff --git a/test/test_def.py b/test/test_def.py
index 44a7854..5c7608f 100644
--- a/test/test_def.py
+++ b/test/test_def.py
@@ -438,6 +438,54 @@ class ScopeTest(TemplateTest):
"this is a, x is 15"
])
+ def test_inline_expression_from_arg_one(self):
+ """test that cache_key=${foo} gets its value from
+ the 'foo' argument in the <%def> tag,
+ and strict_undefined doesn't complain.
+
+ this is #191.
+
+ """
+ t = Template("""
+ <%def name="layout(foo)" cached="True" cache_key="${foo}">
+ foo: ${foo}
+ </%def>
+
+ ${layout(3)}
+ """, strict_undefined=True,
+ cache_impl="plain")
+
+ eq_(
+ result_lines(t.render()),
+ ["foo: 3"]
+ )
+
+ def test_interpret_expression_from_arg_two(self):
+ """test that cache_key=${foo} gets its value from
+ the 'foo' argument regardless of it being passed
+ from the context.
+
+ This is here testing that there's no change
+ to existing behavior before and after #191.
+
+ """
+ t = Template("""
+ <%def name="layout(foo)" cached="True" cache_key="${foo}">
+ foo: ${value}
+ </%def>
+
+ ${layout(3)}
+ """, cache_impl="plain")
+
+ eq_(
+ result_lines(t.render(foo='foo', value=1)),
+ ["foo: 1"]
+ )
+ eq_(
+ result_lines(t.render(foo='bar', value=2)),
+ ["foo: 1"]
+ )
+
class NestedDefTest(TemplateTest):
def test_nested_def(self):
t = Template("""