diff options
author | Mike Bayer <mike_mp@zzzcomputing.com> | 2012-07-07 21:13:48 -0400 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2012-07-07 21:13:48 -0400 |
commit | 03c97d16a8f83d58d629acd8173ce72d2e8dae37 (patch) | |
tree | 4f244a1733d703eaa052d8aff547e03795aac723 | |
parent | 0f58ab39bf6753492e565a85f9f436d476a550b1 (diff) | |
download | mako-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-- | CHANGES | 5 | ||||
-rw-r--r-- | mako/parsetree.py | 2 | ||||
-rw-r--r-- | test/__init__.py | 58 | ||||
-rw-r--r-- | test/test_cache.py | 56 | ||||
-rw-r--r-- | test/test_def.py | 48 |
5 files changed, 127 insertions, 42 deletions
@@ -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(""" |