# mako/cache.py
# Copyright (C) 2006-2016 the Mako authors and contributors <see AUTHORS file>
#
# This module is part of Mako and is released under
# the MIT License: http://www.opensource.org/licenses/mit-license.php

from mako import compat, util

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

register_plugin = _cache_plugins.register
register_plugin("beaker", "mako.ext.beaker_cache", "BeakerCacheImpl")


class Cache(object):

    """Represents a data content cache made available to the module
    space of a specific :class:`.Template` object.

    .. versionadded:: 0.6
       :class:`.Cache` by itself is mostly a
       container for a :class:`.CacheImpl` object, which implements
       a fixed API to provide caching services; specific subclasses exist to
       implement different
       caching strategies.   Mako includes a backend that works with
       the Beaker caching system.   Beaker itself then supports
       a number of backends (i.e. file, memory, memcached, etc.)

    The construction of a :class:`.Cache` is part of the mechanics
    of a :class:`.Template`, and programmatic access to this
    cache is typically via the :attr:`.Template.cache` attribute.

    """

    impl = None
    """Provide the :class:`.CacheImpl` in use by this :class:`.Cache`.

    This accessor allows a :class:`.CacheImpl` with additional
    methods beyond that of :class:`.Cache` to be used programmatically.

    """

    id = None
    """Return the 'id' that identifies this cache.

    This is a value that should be globally unique to the
    :class:`.Template` associated with this cache, and can
    be used by a caching system to name a local container
    for data specific to this template.

    """

    starttime = None
    """Epochal time value for when the owning :class:`.Template` was
    first compiled.

    A cache implementation may wish to invalidate data earlier than
    this timestamp; this has the effect of the cache for a specific
    :class:`.Template` starting clean any time the :class:`.Template`
    is recompiled, such as when the original template file changed on
    the filesystem.

    """

    def __init__(self, template, *args):
        # check for a stale template calling the
        # constructor
        if isinstance(template, compat.string_types) and args:
            return
        self.template = template
        self.id = template.module.__name__
        self.starttime = template.module._modified_time
        self._def_regions = {}
        self.impl = self._load_impl(self.template.cache_impl)

    def _load_impl(self, name):
        return _cache_plugins.load(name)(self)

    def get_or_create(self, key, creation_function, **kw):
        """Retrieve a value from the cache, using the given creation function
        to generate a new value."""

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

    def _ctx_get_or_create(self, key, creation_function, context, **kw):
        """Retrieve a value from the cache, using the given creation function
        to generate a new value."""

        if not self.template.cache_enabled:
            return creation_function()

        return self.impl.get_or_create(
            key,
            creation_function,
            **self._get_cache_kw(kw, context))

    def set(self, key, value, **kw):
        """Place a value in the cache.

        :param key: the value's key.
        :param value: the value.
        :param \**kw: cache configuration arguments.

        """

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

    put = set
    """A synonym for :meth:`.Cache.set`.

    This is here for backwards compatibility.

    """

    def get(self, key, **kw):
        """Retrieve a value from the cache.

        :param key: the value's key.
        :param \**kw: cache configuration arguments.  The
         backend is configured using these arguments upon first request.
         Subsequent requests that use the same series of configuration
         values will use that same backend.

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

    def invalidate(self, key, **kw):
        """Invalidate a value in the cache.

        :param key: the value's key.
        :param \**kw: cache configuration arguments.  The
         backend is configured using these arguments upon first request.
         Subsequent requests that use the same series of configuration
         values will use that same backend.

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

    def invalidate_body(self):
        """Invalidate the cached content of the "body" method for this
        template.

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

    def invalidate_def(self, name):
        """Invalidate the cached content of a particular ``<%def>`` within this
        template.

        """

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

    def invalidate_closure(self, name):
        """Invalidate a nested ``<%def>`` within this template.

        Caching of nested defs is a blunt tool as there is no
        management of scope -- nested defs that use cache tags
        need to have names unique of all other nested defs in the
        template, else their content will be overwritten by
        each other.

        """

        self.invalidate(name, __M_defname=name)

    def _get_cache_kw(self, kw, context):
        defname = kw.pop('__M_defname', None)
        if not defname:
            tmpl_kw = self.template.cache_args.copy()
            tmpl_kw.update(kw)
        elif defname in self._def_regions:
            tmpl_kw = self._def_regions[defname]
        else:
            tmpl_kw = self.template.cache_args.copy()
            tmpl_kw.update(kw)
            self._def_regions[defname] = tmpl_kw
        if context and self.impl.pass_context:
            tmpl_kw = tmpl_kw.copy()
            tmpl_kw.setdefault('context', context)
        return tmpl_kw


class CacheImpl(object):

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

    def __init__(self, cache):
        self.cache = cache

    pass_context = False
    """If ``True``, the :class:`.Context` will be passed to
    :meth:`get_or_create <.CacheImpl.get_or_create>` as the name ``'context'``.
    """

    def get_or_create(self, key, creation_function, **kw):
        """Retrieve a value from the cache, using the given creation function
        to generate a new value.

        This function *must* return a value, either from
        the cache, or via the given creation function.
        If the creation function is called, the newly
        created value should be populated into the cache
        under the given key before being returned.

        :param key: the value's key.
        :param creation_function: function that when called generates
         a new value.
        :param \**kw: cache configuration arguments.

        """
        raise NotImplementedError()

    def set(self, key, value, **kw):
        """Place a value in the cache.

        :param key: the value's key.
        :param value: the value.
        :param \**kw: cache configuration arguments.

        """
        raise NotImplementedError()

    def get(self, key, **kw):
        """Retrieve a value from the cache.

        :param key: the value's key.
        :param \**kw: cache configuration arguments.

        """
        raise NotImplementedError()

    def invalidate(self, key, **kw):
        """Invalidate a value in the cache.

        :param key: the value's key.
        :param \**kw: cache configuration arguments.

        """
        raise NotImplementedError()
