# mako/lookup.py
# Copyright (C) 2006-2015 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

import os
import stat
import posixpath
import re
from mako import exceptions, util
from mako.template import Template

try:
    import threading
except:
    import dummy_threading as threading


class TemplateCollection(object):

    """Represent a collection of :class:`.Template` objects,
    identifiable via URI.

    A :class:`.TemplateCollection` is linked to the usage of
    all template tags that address other templates, such
    as ``<%include>``, ``<%namespace>``, and ``<%inherit>``.
    The ``file`` attribute of each of those tags refers
    to a string URI that is passed to that :class:`.Template`
    object's :class:`.TemplateCollection` for resolution.

    :class:`.TemplateCollection` is an abstract class,
    with the usual default implementation being :class:`.TemplateLookup`.

     """

    def has_template(self, uri):
        """Return ``True`` if this :class:`.TemplateLookup` is
        capable of returning a :class:`.Template` object for the
        given ``uri``.

        :param uri: String URI of the template to be resolved.

        """
        try:
            self.get_template(uri)
            return True
        except exceptions.TemplateLookupException:
            return False

    def get_template(self, uri, relativeto=None):
        """Return a :class:`.Template` object corresponding to the given
        ``uri``.

        The default implementation raises
        :class:`.NotImplementedError`. Implementations should
        raise :class:`.TemplateLookupException` if the given ``uri``
        cannot be resolved.

        :param uri: String URI of the template to be resolved.
        :param relativeto: if present, the given ``uri`` is assumed to
         be relative to this URI.

        """
        raise NotImplementedError()

    def filename_to_uri(self, uri, filename):
        """Convert the given ``filename`` to a URI relative to
           this :class:`.TemplateCollection`."""

        return uri

    def adjust_uri(self, uri, filename):
        """Adjust the given ``uri`` based on the calling ``filename``.

        When this method is called from the runtime, the
        ``filename`` parameter is taken directly to the ``filename``
        attribute of the calling template. Therefore a custom
        :class:`.TemplateCollection` subclass can place any string
        identifier desired in the ``filename`` parameter of the
        :class:`.Template` objects it constructs and have them come back
        here.

        """
        return uri


class TemplateLookup(TemplateCollection):

    """Represent a collection of templates that locates template source files
    from the local filesystem.

    The primary argument is the ``directories`` argument, the list of
    directories to search:

    .. sourcecode:: python

        lookup = TemplateLookup(["/path/to/templates"])
        some_template = lookup.get_template("/index.html")

    The :class:`.TemplateLookup` can also be given :class:`.Template` objects
    programatically using :meth:`.put_string` or :meth:`.put_template`:

    .. sourcecode:: python

        lookup = TemplateLookup()
        lookup.put_string("base.html", '''
            <html><body>${self.next()}</body></html>
        ''')
        lookup.put_string("hello.html", '''
            <%include file='base.html'/>

            Hello, world !
        ''')


    :param directories: A list of directory names which will be
     searched for a particular template URI. The URI is appended
     to each directory and the filesystem checked.

    :param collection_size: Approximate size of the collection used
     to store templates. If left at its default of ``-1``, the size
     is unbounded, and a plain Python dictionary is used to
     relate URI strings to :class:`.Template` instances.
     Otherwise, a least-recently-used cache object is used which
     will maintain the size of the collection approximately to
     the number given.

    :param filesystem_checks: When at its default value of ``True``,
     each call to :meth:`.TemplateLookup.get_template()` will
     compare the filesystem last modified time to the time in
     which an existing :class:`.Template` object was created.
     This allows the :class:`.TemplateLookup` to regenerate a
     new :class:`.Template` whenever the original source has
     been updated. Set this to ``False`` for a very minor
     performance increase.

    :param modulename_callable: A callable which, when present,
     is passed the path of the source file as well as the
     requested URI, and then returns the full path of the
     generated Python module file. This is used to inject
     alternate schemes for Python module location. If left at
     its default of ``None``, the built in system of generation
     based on ``module_directory`` plus ``uri`` is used.

    All other keyword parameters available for
    :class:`.Template` are mirrored here. When new
    :class:`.Template` objects are created, the keywords
    established with this :class:`.TemplateLookup` are passed on
    to each new :class:`.Template`.

    """

    def __init__(self,
                 directories=None,
                 module_directory=None,
                 filesystem_checks=True,
                 collection_size=-1,
                 format_exceptions=False,
                 error_handler=None,
                 disable_unicode=False,
                 bytestring_passthrough=False,
                 output_encoding=None,
                 encoding_errors='strict',

                 cache_args=None,
                 cache_impl='beaker',
                 cache_enabled=True,
                 cache_type=None,
                 cache_dir=None,
                 cache_url=None,

                 modulename_callable=None,
                 module_writer=None,
                 default_filters=None,
                 buffer_filters=(),
                 strict_undefined=False,
                 imports=None,
                 future_imports=None,
                 enable_loop=True,
                 input_encoding=None,
                 preprocessor=None,
                 lexer_cls=None):

        self.directories = [posixpath.normpath(d) for d in
                            util.to_list(directories, ())
                            ]
        self.module_directory = module_directory
        self.modulename_callable = modulename_callable
        self.filesystem_checks = filesystem_checks
        self.collection_size = collection_size

        if cache_args is None:
            cache_args = {}
        # transfer deprecated cache_* args
        if cache_dir:
            cache_args.setdefault('dir', cache_dir)
        if cache_url:
            cache_args.setdefault('url', cache_url)
        if cache_type:
            cache_args.setdefault('type', cache_type)

        self.template_args = {
            'format_exceptions': format_exceptions,
            'error_handler': error_handler,
            'disable_unicode': disable_unicode,
            'bytestring_passthrough': bytestring_passthrough,
            'output_encoding': output_encoding,
            'cache_impl': cache_impl,
            'encoding_errors': encoding_errors,
            'input_encoding': input_encoding,
            'module_directory': module_directory,
            'module_writer': module_writer,
            'cache_args': cache_args,
            'cache_enabled': cache_enabled,
            'default_filters': default_filters,
            'buffer_filters': buffer_filters,
            'strict_undefined': strict_undefined,
            'imports': imports,
            'future_imports': future_imports,
            'enable_loop': enable_loop,
            'preprocessor': preprocessor,
            'lexer_cls': lexer_cls
        }

        if collection_size == -1:
            self._collection = {}
            self._uri_cache = {}
        else:
            self._collection = util.LRUCache(collection_size)
            self._uri_cache = util.LRUCache(collection_size)
        self._mutex = threading.Lock()

    def get_template(self, uri):
        """Return a :class:`.Template` object corresponding to the given
        ``uri``.

        .. note:: The ``relativeto`` argument is not supported here at
           the moment.

        """

        try:
            if self.filesystem_checks:
                return self._check(uri, self._collection[uri])
            else:
                return self._collection[uri]
        except KeyError:
            u = re.sub(r'^\/+', '', uri)
            for dir in self.directories:
                srcfile = posixpath.normpath(posixpath.join(dir, u))
                if os.path.isfile(srcfile):
                    return self._load(srcfile, uri)
            else:
                raise exceptions.TopLevelLookupException(
                    "Cant locate template for uri %r" % uri)

    def adjust_uri(self, uri, relativeto):
        """Adjust the given ``uri`` based on the given relative URI."""

        key = (uri, relativeto)
        if key in self._uri_cache:
            return self._uri_cache[key]

        if uri[0] != '/':
            if relativeto is not None:
                v = self._uri_cache[key] = posixpath.join(
                    posixpath.dirname(relativeto), uri)
            else:
                v = self._uri_cache[key] = '/' + uri
        else:
            v = self._uri_cache[key] = uri
        return v

    def filename_to_uri(self, filename):
        """Convert the given ``filename`` to a URI relative to
           this :class:`.TemplateCollection`."""

        try:
            return self._uri_cache[filename]
        except KeyError:
            value = self._relativeize(filename)
            self._uri_cache[filename] = value
            return value

    def _relativeize(self, filename):
        """Return the portion of a filename that is 'relative'
           to the directories in this lookup.

        """

        filename = posixpath.normpath(filename)
        for dir in self.directories:
            if filename[0:len(dir)] == dir:
                return filename[len(dir):]
        else:
            return None

    def _load(self, filename, uri):
        self._mutex.acquire()
        try:
            try:
                # try returning from collection one
                # more time in case concurrent thread already loaded
                return self._collection[uri]
            except KeyError:
                pass
            try:
                if self.modulename_callable is not None:
                    module_filename = self.modulename_callable(filename, uri)
                else:
                    module_filename = None
                self._collection[uri] = template = Template(
                    uri=uri,
                    filename=posixpath.normpath(filename),
                    lookup=self,
                    module_filename=module_filename,
                    **self.template_args)
                return template
            except:
                # if compilation fails etc, ensure
                # template is removed from collection,
                # re-raise
                self._collection.pop(uri, None)
                raise
        finally:
            self._mutex.release()

    def _check(self, uri, template):
        if template.filename is None:
            return template

        try:
            template_stat = os.stat(template.filename)
            if template.module._modified_time < \
                    template_stat[stat.ST_MTIME]:
                self._collection.pop(uri, None)
                return self._load(template.filename, uri)
            else:
                return template
        except OSError:
            self._collection.pop(uri, None)
            raise exceptions.TemplateLookupException(
                "Cant locate template for uri %r" % uri)

    def put_string(self, uri, text):
        """Place a new :class:`.Template` object into this
        :class:`.TemplateLookup`, based on the given string of
        ``text``.

        """
        self._collection[uri] = Template(
            text,
            lookup=self,
            uri=uri,
            **self.template_args)

    def put_template(self, uri, template):
        """Place a new :class:`.Template` object into this
        :class:`.TemplateLookup`, based on the given
        :class:`.Template` object.

        """
        self._collection[uri] = template
