Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/mako/cache.py: 46%
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1# mako/cache.py
2# Copyright 2006-2025 the Mako authors and contributors <see AUTHORS file>
3#
4# This module is part of Mako and is released under
5# the MIT License: http://www.opensource.org/licenses/mit-license.php
7from mako import util
9_cache_plugins = util.PluginLoader("mako.cache")
11register_plugin = _cache_plugins.register
12register_plugin("beaker", "mako.ext.beaker_cache", "BeakerCacheImpl")
15class Cache:
17 """Represents a data content cache made available to the module
18 space of a specific :class:`.Template` object.
20 .. versionadded:: 0.6
21 :class:`.Cache` by itself is mostly a
22 container for a :class:`.CacheImpl` object, which implements
23 a fixed API to provide caching services; specific subclasses exist to
24 implement different
25 caching strategies. Mako includes a backend that works with
26 the Beaker caching system. Beaker itself then supports
27 a number of backends (i.e. file, memory, memcached, etc.)
29 The construction of a :class:`.Cache` is part of the mechanics
30 of a :class:`.Template`, and programmatic access to this
31 cache is typically via the :attr:`.Template.cache` attribute.
33 """
35 impl = None
36 """Provide the :class:`.CacheImpl` in use by this :class:`.Cache`.
38 This accessor allows a :class:`.CacheImpl` with additional
39 methods beyond that of :class:`.Cache` to be used programmatically.
41 """
43 id = None
44 """Return the 'id' that identifies this cache.
46 This is a value that should be globally unique to the
47 :class:`.Template` associated with this cache, and can
48 be used by a caching system to name a local container
49 for data specific to this template.
51 """
53 starttime = None
54 """Epochal time value for when the owning :class:`.Template` was
55 first compiled.
57 A cache implementation may wish to invalidate data earlier than
58 this timestamp; this has the effect of the cache for a specific
59 :class:`.Template` starting clean any time the :class:`.Template`
60 is recompiled, such as when the original template file changed on
61 the filesystem.
63 """
65 def __init__(self, template, *args):
66 # check for a stale template calling the
67 # constructor
68 if isinstance(template, str) and args:
69 return
70 self.template = template
71 self.id = template.module.__name__
72 self.starttime = template.module._modified_time
73 self._def_regions = {}
74 self.impl = self._load_impl(self.template.cache_impl)
76 def _load_impl(self, name):
77 return _cache_plugins.load(name)(self)
79 def get_or_create(self, key, creation_function, **kw):
80 """Retrieve a value from the cache, using the given creation function
81 to generate a new value."""
83 return self._ctx_get_or_create(key, creation_function, None, **kw)
85 def _ctx_get_or_create(self, key, creation_function, context, **kw):
86 """Retrieve a value from the cache, using the given creation function
87 to generate a new value."""
89 if not self.template.cache_enabled:
90 return creation_function()
92 return self.impl.get_or_create(
93 key, creation_function, **self._get_cache_kw(kw, context)
94 )
96 def set(self, key, value, **kw):
97 r"""Place a value in the cache.
99 :param key: the value's key.
100 :param value: the value.
101 :param \**kw: cache configuration arguments.
103 """
105 self.impl.set(key, value, **self._get_cache_kw(kw, None))
107 put = set
108 """A synonym for :meth:`.Cache.set`.
110 This is here for backwards compatibility.
112 """
114 def get(self, key, **kw):
115 r"""Retrieve a value from the cache.
117 :param key: the value's key.
118 :param \**kw: cache configuration arguments. The
119 backend is configured using these arguments upon first request.
120 Subsequent requests that use the same series of configuration
121 values will use that same backend.
123 """
124 return self.impl.get(key, **self._get_cache_kw(kw, None))
126 def invalidate(self, key, **kw):
127 r"""Invalidate a value in the cache.
129 :param key: the value's key.
130 :param \**kw: cache configuration arguments. The
131 backend is configured using these arguments upon first request.
132 Subsequent requests that use the same series of configuration
133 values will use that same backend.
135 """
136 self.impl.invalidate(key, **self._get_cache_kw(kw, None))
138 def invalidate_body(self):
139 """Invalidate the cached content of the "body" method for this
140 template.
142 """
143 self.invalidate("render_body", __M_defname="render_body")
145 def invalidate_def(self, name):
146 """Invalidate the cached content of a particular ``<%def>`` within this
147 template.
149 """
151 self.invalidate("render_%s" % name, __M_defname="render_%s" % name)
153 def invalidate_closure(self, name):
154 """Invalidate a nested ``<%def>`` within this template.
156 Caching of nested defs is a blunt tool as there is no
157 management of scope -- nested defs that use cache tags
158 need to have names unique of all other nested defs in the
159 template, else their content will be overwritten by
160 each other.
162 """
164 self.invalidate(name, __M_defname=name)
166 def _get_cache_kw(self, kw, context):
167 defname = kw.pop("__M_defname", None)
168 if not defname:
169 tmpl_kw = self.template.cache_args.copy()
170 tmpl_kw.update(kw)
171 elif defname in self._def_regions:
172 tmpl_kw = self._def_regions[defname]
173 else:
174 tmpl_kw = self.template.cache_args.copy()
175 tmpl_kw.update(kw)
176 self._def_regions[defname] = tmpl_kw
177 if context and self.impl.pass_context:
178 tmpl_kw = tmpl_kw.copy()
179 tmpl_kw.setdefault("context", context)
180 return tmpl_kw
183class CacheImpl:
185 """Provide a cache implementation for use by :class:`.Cache`."""
187 def __init__(self, cache):
188 self.cache = cache
190 pass_context = False
191 """If ``True``, the :class:`.Context` will be passed to
192 :meth:`get_or_create <.CacheImpl.get_or_create>` as the name ``'context'``.
193 """
195 def get_or_create(self, key, creation_function, **kw):
196 r"""Retrieve a value from the cache, using the given creation function
197 to generate a new value.
199 This function *must* return a value, either from
200 the cache, or via the given creation function.
201 If the creation function is called, the newly
202 created value should be populated into the cache
203 under the given key before being returned.
205 :param key: the value's key.
206 :param creation_function: function that when called generates
207 a new value.
208 :param \**kw: cache configuration arguments.
210 """
211 raise NotImplementedError()
213 def set(self, key, value, **kw):
214 r"""Place a value in the cache.
216 :param key: the value's key.
217 :param value: the value.
218 :param \**kw: cache configuration arguments.
220 """
221 raise NotImplementedError()
223 def get(self, key, **kw):
224 r"""Retrieve a value from the cache.
226 :param key: the value's key.
227 :param \**kw: cache configuration arguments.
229 """
230 raise NotImplementedError()
232 def invalidate(self, key, **kw):
233 r"""Invalidate a value in the cache.
235 :param key: the value's key.
236 :param \**kw: cache configuration arguments.
238 """
239 raise NotImplementedError()