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