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

69 statements  

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 

6 

7from mako import util 

8 

9_cache_plugins = util.PluginLoader("mako.cache") 

10 

11register_plugin = _cache_plugins.register 

12register_plugin("beaker", "mako.ext.beaker_cache", "BeakerCacheImpl") 

13 

14 

15class Cache: 

16 """Represents a data content cache made available to the module 

17 space of a specific :class:`.Template` object. 

18 

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

27 

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. 

31 

32 """ 

33 

34 impl = None 

35 """Provide the :class:`.CacheImpl` in use by this :class:`.Cache`. 

36 

37 This accessor allows a :class:`.CacheImpl` with additional 

38 methods beyond that of :class:`.Cache` to be used programmatically. 

39 

40 """ 

41 

42 id = None 

43 """Return the 'id' that identifies this cache. 

44 

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. 

49 

50 """ 

51 

52 starttime = None 

53 """Epochal time value for when the owning :class:`.Template` was 

54 first compiled. 

55 

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. 

61 

62 """ 

63 

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) 

74 

75 def _load_impl(self, name): 

76 return _cache_plugins.load(name)(self) 

77 

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

81 

82 return self._ctx_get_or_create(key, creation_function, None, **kw) 

83 

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

87 

88 if not self.template.cache_enabled: 

89 return creation_function() 

90 

91 return self.impl.get_or_create( 

92 key, creation_function, **self._get_cache_kw(kw, context) 

93 ) 

94 

95 def set(self, key, value, **kw): 

96 r"""Place a value in the cache. 

97 

98 :param key: the value's key. 

99 :param value: the value. 

100 :param \**kw: cache configuration arguments. 

101 

102 """ 

103 

104 self.impl.set(key, value, **self._get_cache_kw(kw, None)) 

105 

106 put = set 

107 """A synonym for :meth:`.Cache.set`. 

108 

109 This is here for backwards compatibility. 

110 

111 """ 

112 

113 def get(self, key, **kw): 

114 r"""Retrieve a value from the cache. 

115 

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. 

121 

122 """ 

123 return self.impl.get(key, **self._get_cache_kw(kw, None)) 

124 

125 def invalidate(self, key, **kw): 

126 r"""Invalidate a value in the cache. 

127 

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. 

133 

134 """ 

135 self.impl.invalidate(key, **self._get_cache_kw(kw, None)) 

136 

137 def invalidate_body(self): 

138 """Invalidate the cached content of the "body" method for this 

139 template. 

140 

141 """ 

142 self.invalidate("render_body", __M_defname="render_body") 

143 

144 def invalidate_def(self, name): 

145 """Invalidate the cached content of a particular ``<%def>`` within this 

146 template. 

147 

148 """ 

149 

150 self.invalidate("render_%s" % name, __M_defname="render_%s" % name) 

151 

152 def invalidate_closure(self, name): 

153 """Invalidate a nested ``<%def>`` within this template. 

154 

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. 

160 

161 """ 

162 

163 self.invalidate(name, __M_defname=name) 

164 

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 

180 

181 

182class CacheImpl: 

183 """Provide a cache implementation for use by :class:`.Cache`.""" 

184 

185 def __init__(self, cache): 

186 self.cache = cache 

187 

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

192 

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. 

196 

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. 

202 

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. 

207 

208 """ 

209 raise NotImplementedError() 

210 

211 def set(self, key, value, **kw): 

212 r"""Place a value in the cache. 

213 

214 :param key: the value's key. 

215 :param value: the value. 

216 :param \**kw: cache configuration arguments. 

217 

218 """ 

219 raise NotImplementedError() 

220 

221 def get(self, key, **kw): 

222 r"""Retrieve a value from the cache. 

223 

224 :param key: the value's key. 

225 :param \**kw: cache configuration arguments. 

226 

227 """ 

228 raise NotImplementedError() 

229 

230 def invalidate(self, key, **kw): 

231 r"""Invalidate a value in the cache. 

232 

233 :param key: the value's key. 

234 :param \**kw: cache configuration arguments. 

235 

236 """ 

237 raise NotImplementedError()