From 64eb92621e5a1a1fad2e5ff4049706668bfca459 Mon Sep 17 00:00:00 2001
From: Mike Bayer <mike_mp@zzzcomputing.com>
Date: Fri, 17 Oct 2008 14:40:07 +0000
Subject: [PATCH] cache sends in a "defname" parameter so that the cache can
 map settings to that name, instead of the key. eliminates the need to store
 all Value objects which will use up RAM in a dynamic-key scenario.

---
 doc/build/content/caching.txt |  9 +++++----
 lib/mako/cache.py             | 25 +++++++++++++------------
 lib/mako/codegen.py           |  6 +++---
 test/cache.py                 |  2 +-
 4 files changed, 22 insertions(+), 20 deletions(-)

diff --git a/doc/build/content/caching.txt b/doc/build/content/caching.txt
index 7e018d7..7e0c0b3 100644
--- a/doc/build/content/caching.txt
+++ b/doc/build/content/caching.txt
@@ -32,11 +32,11 @@ The options available are:
 In the case of the `memcached` type, this attribute is required and it's used to store the lock files.
 * cache_key - the "key" used to uniquely identify this content in the cache.  the total namespace of keys within the cache is local to the current template, and the default value of "key" is the name of the def which is storing its data.  It is an evaluable tag, so you can put a Python expression to calculate the value of the key on the fly.  For example, heres a page that caches any page which inherits from it, based on the filename of the calling template:
     
-    <%page cached="True" cache_key="${self.filename}"/>
+        <%page cached="True" cache_key="${self.filename}"/>
     
-    ${next.body()}
+        ${next.body()}
         
-    ## rest of template
+        ## rest of template
     
 ### Accessing the Cache {@name=accessing}
 
@@ -60,4 +60,5 @@ More commonly the `cache` object is used to invalidate cached sections programma
     template.cache.invalidate_def('somedef')
     
     # invalidate an arbitrary key
-    template.cache.invalidate('somekey')
\ No newline at end of file
+    template.cache.invalidate('somekey')
+    
\ No newline at end of file
diff --git a/lib/mako/cache.py b/lib/mako/cache.py
index a539523..20ceba7 100644
--- a/lib/mako/cache.py
+++ b/lib/mako/cache.py
@@ -16,7 +16,7 @@ class Cache(object):
         self.starttime = starttime
         if container is not None:
             self.context = container.ContainerContext()
-        self._values = {}
+        self.def_regions = {}
         
     def put(self, key, value, **kwargs):
         c = self._get_container(key, **kwargs)
@@ -31,29 +31,30 @@ class Cache(object):
         else:
             return None
         
-    def invalidate(self, key, **kwargs):
-        c = self._get_container(key, **kwargs)
+    def invalidate(self, key, defname, **kwargs):
+        c = self._get_container(key, defname, **kwargs)
         if c:
             c.clear_value()
     
     def invalidate_body(self):
-        self.invalidate('render_body')
+        self.invalidate('render_body', 'render_body')
     
     def invalidate_def(self, name):
-        self.invalidate('render_%s' % name)
+        self.invalidate('render_%s' % name, 'render_%s' % name)
         
     def invalidate_closure(self, name):
-        self.invalidate(name)
+        self.invalidate(name, name)
         
-    def _get_container(self, key, **kwargs):
+    def _get_container(self, key, defname, **kwargs):
         if not container:
             raise exceptions.RuntimeException("the Beaker package is required to use cache functionality.")
         
-        if kwargs:
-            type = kwargs.pop('type', 'memory')
-            self._values[key] = k = container.Value(key, self.context, self.id, clsmap[type], starttime=self.starttime, **kwargs)
-            return k
+        type = kwargs.pop('type', None)
+        if not type:
+            type = self.def_regions.get(defname, 'memory')
         else:
-            return self._values.get(key, None)
+            self.def_regions[defname] = type
+
+        return container.Value(key, self.context, self.id, clsmap[type], starttime=self.starttime, **kwargs)
 
 
diff --git a/lib/mako/codegen.py b/lib/mako/codegen.py
index 3b1d531..0f1be99 100644
--- a/lib/mako/codegen.py
+++ b/lib/mako/codegen.py
@@ -11,7 +11,7 @@ import re
 from mako.pygen import PythonPrinter
 from mako import util, ast, parsetree, filters
 
-MAGIC_NUMBER = 4
+MAGIC_NUMBER = 5
 
 
 def compile(node, uri, filename=None, default_filters=None, buffer_filters=None, imports=None, source_encoding=None, generate_unicode=True):
@@ -428,13 +428,13 @@ class _GenerateRenderMethod(object):
 
         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))" % (cachekey, ''.join(["%s=%s, " % (k,v) for k, v in cacheargs.iteritems()]), name, ','.join(pass_args))
+            s = "context.get('local').get_cached(%s, defname=%r, %screatefunc=lambda:__M_%s(%s))" % (cachekey, name, ''.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(
-                    "__M_writer(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)),
+                    "__M_writer(context.get('local').get_cached(%s, defname=%r, %screatefunc=lambda:__M_%s(%s)))" % (cachekey, name, ''.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 cca53b6..80f6416 100644
--- a/test/cache.py
+++ b/test/cache.py
@@ -19,6 +19,7 @@ class MockCache(object):
         self.key = key
         self.kwargs = kwargs.copy()
         self.kwargs.pop('createfunc', None)
+        self.kwargs.pop('defname', None)
         return self.realcache.get(key, **kwargs)
     
 class CacheTest(unittest.TestCase):
@@ -363,7 +364,6 @@ class CacheTest(unittest.TestCase):
             </%def>
             ${foo()} ${bar()}
         """)
-
         assert result_lines(t.render(x=1)) == ["foo: 1", "bar: 1"]
         assert result_lines(t.render(x=2)) == ["foo: 1", "bar: 1"]
         t.cache.invalidate_def('foo')
-- 
GitLab