- cache_key argument can now render arguments passed
directly to the %page or %def, i.e.
<%def name="foo(x)" cached="True" cache_key="${x}"/>
[ticket:78]
diff --git a/CHANGES b/CHANGES
index 4e5a3ce..72ed906 100644
--- a/CHANGES
+++ b/CHANGES
@@ -19,6 +19,10 @@
- rewrote the "whitespace adjuster" function to work with
more elaborate combinations of quotes and comments
[ticket:75]
+- cache_key argument can now render arguments passed
+ directly to the %page or %def, i.e.
+ <%def name="foo(x)" cached="True" cache_key="${x}"/>
+ [ticket:78]
0.1.10
- fixed propagation of 'caller' such that nested %def calls
diff --git a/lib/mako/codegen.py b/lib/mako/codegen.py
index 5d974bc..523c3b0 100644
--- a/lib/mako/codegen.py
+++ b/lib/mako/codegen.py
@@ -176,8 +176,8 @@
self.printer.writeline(None)
self.printer.write("\n\n")
if cached:
- self.write_cache_decorator(node, name, buffered, self.identifiers, toplevel=True)
-
+ self.write_cache_decorator(node, name, args, buffered, self.identifiers, toplevel=True)
+
def write_module_code(self, module_code):
"""write module-level template code, i.e. that which is enclosed in <%! %> tags
in the template."""
@@ -340,8 +340,8 @@
self.write_def_finish(node, buffered, filtered, cached)
self.printer.writeline(None)
if cached:
- self.write_cache_decorator(node, node.name, False, identifiers, inline=True, toplevel=False)
-
+ self.write_cache_decorator(node, node.name, namedecls, False, identifiers, inline=True, toplevel=False)
+
def write_def_finish(self, node, buffered, filtered, cached, callstack=True):
"""write the end section of a rendering function, either outermost or inline.
@@ -377,7 +377,7 @@
"return ''"
)
- def write_cache_decorator(self, node_or_pagetag, name, buffered, identifiers, inline=False, toplevel=False):
+ def write_cache_decorator(self, node_or_pagetag, name, args, buffered, identifiers, inline=False, toplevel=False):
"""write a post-function decorator to replace a rendering callable with a cached version of itself."""
self.printer.writeline("__M_%s = %s" % (name, name))
cachekey = node_or_pagetag.parsed_attributes.get('cache_key', repr(name))
@@ -398,22 +398,22 @@
else:
cacheargs[arg[1]] = val
- if inline:
- ctx_arg = ""
- else:
- ctx_arg = "context, "
-
- self.printer.writeline("def %s(%s*args, **kwargs):" % (name, ctx_arg))
+ self.printer.writeline("def %s(%s):" % (name, ','.join(args)))
+
+ self.write_variable_declares(identifiers, toplevel=toplevel, limit=node_or_pagetag.undeclared_identifiers())
+
+ # form "arg1, arg2, arg3=arg3, arg4=arg4", etc.
+ pass_args = [ '=' in a and "%s=%s" % ((a.split('=')[0],)*2) or a for a in args]
self.write_variable_declares(identifiers, toplevel=toplevel, limit=node_or_pagetag.undeclared_identifiers())
if buffered:
- s = "context.get('local').get_cached(%s, %screatefunc=lambda:__M_%s(%s*args, **kwargs))" % (cachekey, ''.join(["%s=%s, " % (k,v) for k, v in cacheargs.iteritems()]), name, ctx_arg)
+ s = "context.get('local').get_cached(%s, %screatefunc=lambda:__M_%s(%s))" % (cachekey, ''.join(["%s=%s, " % (k,v) for k, v in cacheargs.iteritems()]), name, ','.join(pass_args))
# apply buffer_filters
s = self.create_filter_callable(self.compiler.buffer_filters, s, False)
self.printer.writelines("return " + s,None)
else:
self.printer.writelines(
- "context.write(context.get('local').get_cached(%s, %screatefunc=lambda:__M_%s(%s*args, **kwargs)))" % (cachekey, ''.join(["%s=%s, " % (k,v) for k, v in cacheargs.iteritems()]), name, ctx_arg),
+ "context.write(context.get('local').get_cached(%s, %screatefunc=lambda:__M_%s(%s)))" % (cachekey, ''.join(["%s=%s, " % (k,v) for k, v in cacheargs.iteritems()]), name, ','.join(pass_args)),
"return ''",
None
)
diff --git a/test/cache.py b/test/cache.py
index b3ddf12..45674da 100644
--- a/test/cache.py
+++ b/test/cache.py
@@ -92,7 +92,43 @@
"callcount: [1]"
]
assert m.kwargs == {}
-
+
+ def test_dynamic_key_with_funcargs(self):
+ t = Template("""
+ <%def name="foo(num=5)" cached="True" cache_key="foo_${str(num)}">
+ hi
+ </%def>
+
+ ${foo()}
+ """)
+ m = self._install_mock_cache(t)
+ t.render()
+ t.render()
+ assert result_lines(t.render()) == ['hi']
+ assert m.key == "foo_5"
+
+ t = Template("""
+ <%def name="foo(*args, **kwargs)" cached="True" cache_key="foo_${kwargs['bar']}">
+ hi
+ </%def>
+
+ ${foo(1, 2, bar='lala')}
+ """)
+ m = self._install_mock_cache(t)
+ t.render()
+ assert result_lines(t.render()) == ['hi']
+ assert m.key == "foo_lala"
+
+ t = Template('''
+ <%page args="bar='hi'" cache_key="foo_${bar}" cached="True"/>
+ hi
+ ''')
+ m = self._install_mock_cache(t)
+ t.render()
+ 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", """