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-2026 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:
16 """Represents a data content cache made available to the module
17 space of a specific :class:`.Template` object.
19 .. versionadded:: 0.6
20 :class:`.Cache` by itself is mostly a
21 container for a :class:`.CacheImpl` object, which implements
22 a fixed API to provide caching services; specific subclasses exist to
23 implement different
24 caching strategies. Mako includes a backend that works with
25 the Beaker caching system. Beaker itself then supports
26 a number of backends (i.e. file, memory, memcached, etc.)
28 The construction of a :class:`.Cache` is part of the mechanics
29 of a :class:`.Template`, and programmatic access to this
30 cache is typically via the :attr:`.Template.cache` attribute.
32 """
34 impl = None
35 """Provide the :class:`.CacheImpl` in use by this :class:`.Cache`.
37 This accessor allows a :class:`.CacheImpl` with additional
38 methods beyond that of :class:`.Cache` to be used programmatically.
40 """
42 id = None
43 """Return the 'id' that identifies this cache.
45 This is a value that should be globally unique to the
46 :class:`.Template` associated with this cache, and can
47 be used by a caching system to name a local container
48 for data specific to this template.
50 """
52 starttime = None
53 """Epochal time value for when the owning :class:`.Template` was
54 first compiled.
56 A cache implementation may wish to invalidate data earlier than
57 this timestamp; this has the effect of the cache for a specific
58 :class:`.Template` starting clean any time the :class:`.Template`
59 is recompiled, such as when the original template file changed on
60 the filesystem.
62 """
64 def __init__(self, template, *args):
65 # check for a stale template calling the
66 # constructor
67 if isinstance(template, str) and args:
68 return
69 self.template = template
70 self.id = template.module.__name__
71 self.starttime = template.module._modified_time
72 self._def_regions = {}
73 self.impl = self._load_impl(self.template.cache_impl)
75 def _load_impl(self, name):
76 return _cache_plugins.load(name)(self)
78 def get_or_create(self, key, creation_function, **kw):
79 """Retrieve a value from the cache, using the given creation function
80 to generate a new value."""
82 return self._ctx_get_or_create(key, creation_function, None, **kw)
84 def _ctx_get_or_create(self, key, creation_function, context, **kw):
85 """Retrieve a value from the cache, using the given creation function
86 to generate a new value."""
88 if not self.template.cache_enabled:
89 return creation_function()
91 return self.impl.get_or_create(
92 key, creation_function, **self._get_cache_kw(kw, context)
93 )
95 def set(self, key, value, **kw):
96 r"""Place a value in the cache.
98 :param key: the value's key.
99 :param value: the value.
100 :param \**kw: cache configuration arguments.
102 """
104 self.impl.set(key, value, **self._get_cache_kw(kw, None))
106 put = set
107 """A synonym for :meth:`.Cache.set`.
109 This is here for backwards compatibility.
111 """
113 def get(self, key, **kw):
114 r"""Retrieve a value from the cache.
116 :param key: the value's key.
117 :param \**kw: cache configuration arguments. The
118 backend is configured using these arguments upon first request.
119 Subsequent requests that use the same series of configuration
120 values will use that same backend.
122 """
123 return self.impl.get(key, **self._get_cache_kw(kw, None))
125 def invalidate(self, key, **kw):
126 r"""Invalidate a value in the cache.
128 :param key: the value's key.
129 :param \**kw: cache configuration arguments. The
130 backend is configured using these arguments upon first request.
131 Subsequent requests that use the same series of configuration
132 values will use that same backend.
134 """
135 self.impl.invalidate(key, **self._get_cache_kw(kw, None))
137 def invalidate_body(self):
138 """Invalidate the cached content of the "body" method for this
139 template.
141 """
142 self.invalidate("render_body", __M_defname="render_body")
144 def invalidate_def(self, name):
145 """Invalidate the cached content of a particular ``<%def>`` within this
146 template.
148 """
150 self.invalidate("render_%s" % name, __M_defname="render_%s" % name)
152 def invalidate_closure(self, name):
153 """Invalidate a nested ``<%def>`` within this template.
155 Caching of nested defs is a blunt tool as there is no
156 management of scope -- nested defs that use cache tags
157 need to have names unique of all other nested defs in the
158 template, else their content will be overwritten by
159 each other.
161 """
163 self.invalidate(name, __M_defname=name)
165 def _get_cache_kw(self, kw, context):
166 defname = kw.pop("__M_defname", None)
167 if not defname:
168 tmpl_kw = self.template.cache_args.copy()
169 tmpl_kw.update(kw)
170 elif defname in self._def_regions:
171 tmpl_kw = self._def_regions[defname]
172 else:
173 tmpl_kw = self.template.cache_args.copy()
174 tmpl_kw.update(kw)
175 self._def_regions[defname] = tmpl_kw
176 if context and self.impl.pass_context:
177 tmpl_kw = tmpl_kw.copy()
178 tmpl_kw.setdefault("context", context)
179 return tmpl_kw
182class CacheImpl:
183 """Provide a cache implementation for use by :class:`.Cache`."""
185 def __init__(self, cache):
186 self.cache = cache
188 pass_context = False
189 """If ``True``, the :class:`.Context` will be passed to
190 :meth:`get_or_create <.CacheImpl.get_or_create>` as the name ``'context'``.
191 """
193 def get_or_create(self, key, creation_function, **kw):
194 r"""Retrieve a value from the cache, using the given creation function
195 to generate a new value.
197 This function *must* return a value, either from
198 the cache, or via the given creation function.
199 If the creation function is called, the newly
200 created value should be populated into the cache
201 under the given key before being returned.
203 :param key: the value's key.
204 :param creation_function: function that when called generates
205 a new value.
206 :param \**kw: cache configuration arguments.
208 """
209 raise NotImplementedError()
211 def set(self, key, value, **kw):
212 r"""Place a value in the cache.
214 :param key: the value's key.
215 :param value: the value.
216 :param \**kw: cache configuration arguments.
218 """
219 raise NotImplementedError()
221 def get(self, key, **kw):
222 r"""Retrieve a value from the cache.
224 :param key: the value's key.
225 :param \**kw: cache configuration arguments.
227 """
228 raise NotImplementedError()
230 def invalidate(self, key, **kw):
231 r"""Invalidate a value in the cache.
233 :param key: the value's key.
234 :param \**kw: cache configuration arguments.
236 """
237 raise NotImplementedError()