Commits

Mike Bayer committed b64d6f4

- 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]

  • Participants
  • Parent commits 3a31591

Comments (0)

Files changed (3)

 - 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

lib/mako/codegen.py

         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."""
         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.
         
                     "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))
                         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
             )
             "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", """