Skip to content
Snippets Groups Projects
Commit 03c97d16 authored by Mike Bayer's avatar Mike Bayer
Browse files

- [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]
parent 0f58ab39
No related branches found
No related tags found
No related merge requests found
...@@ -4,6 +4,11 @@ ...@@ -4,6 +4,11 @@
when no statements are otherwise present. when no statements are otherwise present.
Courtesy Ben Trofatter [ticket:146] 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 0.7.0
- [feature] Added new "loop" variable to templates, - [feature] Added new "loop" variable to templates,
is provided within a % for block to provide is provided within a % for block to provide
......
...@@ -445,6 +445,8 @@ class DefTag(Tag): ...@@ -445,6 +445,8 @@ class DefTag(Tag):
difference(filters.DEFAULT_ESCAPES.keys()) difference(filters.DEFAULT_ESCAPES.keys())
).union( ).union(
self.expression_undeclared_identifiers self.expression_undeclared_identifiers
).difference(
self.function_decl.argnames
) )
class BlockTag(Tag): class BlockTag(Tag):
......
...@@ -3,7 +3,7 @@ import unittest, os ...@@ -3,7 +3,7 @@ import unittest, os
from mako.util import py3k from mako.util import py3k
from mako.util import function_named from mako.util import function_named
import re import re
from mako.cache import CacheImpl, register_plugin
from nose import SkipTest from nose import SkipTest
...@@ -11,34 +11,34 @@ template_base = os.path.join(os.path.dirname(__file__), 'templates') ...@@ -11,34 +11,34 @@ template_base = os.path.join(os.path.dirname(__file__), 'templates')
module_base = os.path.join(template_base, 'modules') module_base = os.path.join(template_base, 'modules')
class TemplateTest(unittest.TestCase): class TemplateTest(unittest.TestCase):
def _file_template(self, filename, **kw): def _file_template(self, filename, **kw):
filepath = self._file_path(filename) filepath = self._file_path(filename)
return Template(uri=filename, filename=filepath, return Template(uri=filename, filename=filepath,
module_directory=module_base, **kw) module_directory=module_base, **kw)
def _file_path(self, filename): def _file_path(self, filename):
name, ext = os.path.splitext(filename) name, ext = os.path.splitext(filename)
if py3k: if py3k:
py3k_path = os.path.join(template_base, name + "_py3k" + ext) py3k_path = os.path.join(template_base, name + "_py3k" + ext)
if os.path.exists(py3k_path): if os.path.exists(py3k_path):
return py3k_path return py3k_path
return os.path.join(template_base, filename) 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): unicode_=True, template_args=None, **kw):
t1 = self._file_template(filename, **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) 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): unicode_=True, template_args=None, **kw):
t1 = Template(text=source, **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) unicode_=unicode_, template_args=template_args)
def _do_test(self, template, expected, filters=None, template_args=None, unicode_=True): def _do_test(self, template, expected, filters=None, template_args=None, unicode_=True):
if template_args is None: if template_args is None:
template_args = {} template_args = {}
...@@ -46,11 +46,11 @@ class TemplateTest(unittest.TestCase): ...@@ -46,11 +46,11 @@ class TemplateTest(unittest.TestCase):
output = template.render_unicode(**template_args) output = template.render_unicode(**template_args)
else: else:
output = template.render(**template_args) output = template.render(**template_args)
if filters: if filters:
output = filters(output) output = filters(output)
eq_(output, expected) eq_(output, expected)
def eq_(a, b, msg=None): def eq_(a, b, msg=None):
"""Assert a == b, with repr messaging on failure.""" """Assert a == b, with repr messaging on failure."""
assert a == b, msg or "%r != %r" % (a, b) assert a == b, msg or "%r != %r" % (a, b)
...@@ -65,7 +65,7 @@ def assert_raises(except_cls, callable_, *args, **kw): ...@@ -65,7 +65,7 @@ def assert_raises(except_cls, callable_, *args, **kw):
success = False success = False
except except_cls, e: except except_cls, e:
success = True success = True
# assert outside the block so it works for AssertionError too ! # assert outside the block so it works for AssertionError too !
assert success, "Callable did not raise an exception" assert success, "Callable did not raise an exception"
...@@ -106,4 +106,30 @@ def requires_no_pygments(fn): ...@@ -106,4 +106,30 @@ def requires_no_pygments(fn):
import pygments import pygments
except: except:
pygments = None pygments = None
return skip_if(lambda:pygments is not None)(fn) return skip_if(lambda: pygments is not None)(fn)
\ No newline at end of file
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")
...@@ -12,14 +12,17 @@ try: ...@@ -12,14 +12,17 @@ try:
except: except:
from nose import SkipTest from nose import SkipTest
raise SkipTest("Beaker is required for these tests.") raise SkipTest("Beaker is required for these tests.")
from mako.cache import register_plugin, CacheImpl from mako.cache import register_plugin, CacheImpl
class MockCacheImpl(CacheImpl): class MockCacheImpl(CacheImpl):
realcacheimpl = None realcacheimpl = None
def __init__(self, cache): def __init__(self, cache):
self.cache = 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: if use_beaker:
self.realcacheimpl = cache._load_impl("beaker") self.realcacheimpl = cache._load_impl("beaker")
...@@ -27,7 +30,8 @@ class MockCacheImpl(CacheImpl): ...@@ -27,7 +30,8 @@ class MockCacheImpl(CacheImpl):
self.key = key self.key = key
self.kwargs = kw.copy() self.kwargs = kw.copy()
if self.realcacheimpl: if self.realcacheimpl:
return self.realcacheimpl.get_or_create(key, creation_function, **kw) return self.realcacheimpl.\
get_or_create(key, creation_function, **kw)
else: else:
return creation_function() return creation_function()
...@@ -36,13 +40,13 @@ class MockCacheImpl(CacheImpl): ...@@ -36,13 +40,13 @@ class MockCacheImpl(CacheImpl):
self.kwargs = kw.copy() self.kwargs = kw.copy()
if self.realcacheimpl: if self.realcacheimpl:
self.realcacheimpl.put(key, value, **kw) self.realcacheimpl.put(key, value, **kw)
def get(self, key, **kw): def get(self, key, **kw):
self.key = key self.key = key
self.kwargs = kw.copy() self.kwargs = kw.copy()
if self.realcacheimpl: if self.realcacheimpl:
return self.realcacheimpl.get(key, **kw) return self.realcacheimpl.get(key, **kw)
def invalidate(self, key, **kw): def invalidate(self, key, **kw):
self.key = key self.key = key
self.kwargs = kw.copy() self.kwargs = kw.copy()
...@@ -104,7 +108,7 @@ class CacheTest(TemplateTest): ...@@ -104,7 +108,7 @@ class CacheTest(TemplateTest):
callcount[0] += 1 callcount[0] += 1
%> %>
</%def> </%def>
${foo()} ${foo()}
${foo()} ${foo()}
${foo()} ${foo()}
...@@ -134,7 +138,7 @@ class CacheTest(TemplateTest): ...@@ -134,7 +138,7 @@ class CacheTest(TemplateTest):
m = self._install_mock_cache(t) m = self._install_mock_cache(t)
eq_(t.render().strip(), "callcount: [2]") eq_(t.render().strip(), "callcount: [2]")
def test_nested_def(self): def test_nested_def(self):
t = Template(""" t = Template("""
<%! <%!
...@@ -163,7 +167,7 @@ class CacheTest(TemplateTest): ...@@ -163,7 +167,7 @@ class CacheTest(TemplateTest):
'callcount: [1]', 'callcount: [1]',
] ]
assert m.kwargs == {} assert m.kwargs == {}
def test_page(self): def test_page(self):
t = Template(""" t = Template("""
<%! <%!
...@@ -251,7 +255,7 @@ class CacheTest(TemplateTest): ...@@ -251,7 +255,7 @@ class CacheTest(TemplateTest):
assert result_lines(t.render()) == ['hi'] assert result_lines(t.render()) == ['hi']
assert m.key == "foo_hi" assert m.key == "foo_hi"
def test_dynamic_key_with_imports(self): def test_dynamic_key_with_imports(self):
lookup = TemplateLookup() lookup = TemplateLookup()
lookup.put_string("foo.html", """ lookup.put_string("foo.html", """
...@@ -276,7 +280,7 @@ class CacheTest(TemplateTest): ...@@ -276,7 +280,7 @@ class CacheTest(TemplateTest):
"callcount: [1]" "callcount: [1]"
] ]
assert m.kwargs == {} assert m.kwargs == {}
def test_fileargs_implicit(self): def test_fileargs_implicit(self):
l = lookup.TemplateLookup(module_directory=module_base) l = lookup.TemplateLookup(module_directory=module_base)
l.put_string("test",""" l.put_string("test","""
...@@ -295,7 +299,7 @@ class CacheTest(TemplateTest): ...@@ -295,7 +299,7 @@ class CacheTest(TemplateTest):
${foo()} ${foo()}
callcount: ${callcount} callcount: ${callcount}
""") """)
m = self._install_mock_cache(l.get_template('test')) m = self._install_mock_cache(l.get_template('test'))
assert result_lines(l.get_template('test').render()) == [ assert result_lines(l.get_template('test').render()) == [
'this is foo', 'this is foo',
...@@ -304,7 +308,7 @@ class CacheTest(TemplateTest): ...@@ -304,7 +308,7 @@ class CacheTest(TemplateTest):
'callcount: [1]', 'callcount: [1]',
] ]
eq_(m.kwargs, {'type':'dbm'}) eq_(m.kwargs, {'type':'dbm'})
def test_fileargs_deftag(self): def test_fileargs_deftag(self):
t = Template(""" t = Template("""
<%%! <%%!
...@@ -369,7 +373,7 @@ class CacheTest(TemplateTest): ...@@ -369,7 +373,7 @@ class CacheTest(TemplateTest):
m = self._install_mock_cache(t) m = self._install_mock_cache(t)
t.render() t.render()
eq_(m.kwargs, {'dir':module_base, 'type':'file', 'timeout':30}) eq_(m.kwargs, {'dir':module_base, 'type':'file', 'timeout':30})
t2 = Template(""" t2 = Template("""
<%%page cached="True" cache_timeout="30" cache_dir="%s" cache_type="file" cache_key='somekey'/> <%%page cached="True" cache_timeout="30" cache_dir="%s" cache_type="file" cache_key='somekey'/>
hi hi
...@@ -396,7 +400,7 @@ class CacheTest(TemplateTest): ...@@ -396,7 +400,7 @@ class CacheTest(TemplateTest):
${foo()} ${foo()}
callcount: ${callcount} callcount: ${callcount}
""") """)
t = l.get_template('test') t = l.get_template('test')
m = self._install_mock_cache(t) m = self._install_mock_cache(t)
assert result_lines(l.get_template('test').render()) == [ assert result_lines(l.get_template('test').render()) == [
...@@ -406,7 +410,7 @@ class CacheTest(TemplateTest): ...@@ -406,7 +410,7 @@ class CacheTest(TemplateTest):
'callcount: [1]', 'callcount: [1]',
] ]
eq_(m.kwargs, {'dir':module_base, 'type':'file'}) eq_(m.kwargs, {'dir':module_base, 'type':'file'})
def test_buffered(self): def test_buffered(self):
t = Template(""" t = Template("""
<%! <%!
...@@ -420,11 +424,11 @@ class CacheTest(TemplateTest): ...@@ -420,11 +424,11 @@ class CacheTest(TemplateTest):
</%def> </%def>
""", buffer_filters=["a"]) """, buffer_filters=["a"])
assert result_lines(t.render()) == ["this is a this is a test", "this is a this is a test"] 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): def test_load_from_expired(self):
"""test that the cache callable can be called safely after the """test that the cache callable can be called safely after the
originating template has completed rendering. originating template has completed rendering.
""" """
t = Template(""" t = Template("""
${foo()} ${foo()}
...@@ -432,12 +436,12 @@ class CacheTest(TemplateTest): ...@@ -432,12 +436,12 @@ class CacheTest(TemplateTest):
foo foo
</%def> </%def>
""") """)
x1 = t.render() x1 = t.render()
time.sleep(3) time.sleep(3)
x2 = t.render() x2 = t.render()
assert x1.strip() == x2.strip() == "foo" assert x1.strip() == x2.strip() == "foo"
def test_cache_uses_current_context(self): def test_cache_uses_current_context(self):
t = Template(""" t = Template("""
${foo()} ${foo()}
...@@ -445,7 +449,7 @@ class CacheTest(TemplateTest): ...@@ -445,7 +449,7 @@ class CacheTest(TemplateTest):
foo: ${x} foo: ${x}
</%def> </%def>
""") """)
x1 = t.render(x=1) x1 = t.render(x=1)
time.sleep(3) time.sleep(3)
x2 = t.render(x=2) x2 = t.render(x=2)
...@@ -496,10 +500,10 @@ class CacheTest(TemplateTest): ...@@ -496,10 +500,10 @@ class CacheTest(TemplateTest):
assert result_lines(t.render(x=3)) == ["foo: 3", "bar: 1"] assert result_lines(t.render(x=3)) == ["foo: 3", "bar: 1"]
t.cache.invalidate_def('bar') t.cache.invalidate_def('bar')
assert result_lines(t.render(x=4)) == ["foo: 3", "bar: 4"] assert result_lines(t.render(x=4)) == ["foo: 3", "bar: 4"]
t = Template(""" t = Template("""
<%%page cached="True" cache_type="dbm" cache_dir="%s"/> <%%page cached="True" cache_type="dbm" cache_dir="%s"/>
page: ${x} page: ${x}
""" % module_base) """ % module_base)
assert result_lines(t.render(x=1)) == ["page: 1"] assert result_lines(t.render(x=1)) == ["page: 1"]
...@@ -507,10 +511,10 @@ class CacheTest(TemplateTest): ...@@ -507,10 +511,10 @@ class CacheTest(TemplateTest):
t.cache.invalidate_body() t.cache.invalidate_body()
assert result_lines(t.render(x=3)) == ["page: 3"] assert result_lines(t.render(x=3)) == ["page: 3"]
assert result_lines(t.render(x=4)) == ["page: 3"] assert result_lines(t.render(x=4)) == ["page: 3"]
def test_custom_args_def(self): def test_custom_args_def(self):
t = Template(""" t = Template("""
<%def name="foo()" cached="True" cache_region="myregion" <%def name="foo()" cached="True" cache_region="myregion"
cache_timeout="50" cache_foo="foob"> cache_timeout="50" cache_foo="foob">
</%def> </%def>
${foo()} ${foo()}
...@@ -521,7 +525,7 @@ class CacheTest(TemplateTest): ...@@ -521,7 +525,7 @@ class CacheTest(TemplateTest):
def test_custom_args_block(self): def test_custom_args_block(self):
t = Template(""" t = Template("""
<%block name="foo" cached="True" cache_region="myregion" <%block name="foo" cached="True" cache_region="myregion"
cache_timeout="50" cache_foo="foob"> cache_timeout="50" cache_foo="foob">
</%block> </%block>
""", cache_args={'use_beaker':False}) """, cache_args={'use_beaker':False})
...@@ -531,7 +535,7 @@ class CacheTest(TemplateTest): ...@@ -531,7 +535,7 @@ class CacheTest(TemplateTest):
def test_custom_args_page(self): def test_custom_args_page(self):
t = Template(""" t = Template("""
<%page cached="True" cache_region="myregion" <%page cached="True" cache_region="myregion"
cache_timeout="50" cache_foo="foob"/> cache_timeout="50" cache_foo="foob"/>
""", cache_args={'use_beaker':False}) """, cache_args={'use_beaker':False})
m = self._install_mock_cache(t) m = self._install_mock_cache(t)
......
...@@ -438,6 +438,54 @@ class ScopeTest(TemplateTest): ...@@ -438,6 +438,54 @@ class ScopeTest(TemplateTest):
"this is a, x is 15" "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): class NestedDefTest(TemplateTest):
def test_nested_def(self): def test_nested_def(self):
t = Template(""" t = Template("""
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment