# mako/template.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

"""Provides the Template class, a facade for parsing, generating and executing
template strings, as well as template runtime operations."""

from mako.lexer import Lexer
from mako import runtime, util, exceptions, codegen, cache, compat
import os
import re
import shutil
import stat
import sys
import tempfile
import types
import weakref


class Template(object):

    """Represents a compiled template.

    :class:`.Template` includes a reference to the original
    template source (via the :attr:`.source` attribute)
    as well as the source code of the
    generated Python module (i.e. the :attr:`.code` attribute),
    as well as a reference to an actual Python module.

    :class:`.Template` is constructed using either a literal string
    representing the template text, or a filename representing a filesystem
    path to a source file.

    :param text: textual template source.  This argument is mutually
     exclusive versus the ``filename`` parameter.

    :param filename: filename of the source template.  This argument is
     mutually exclusive versus the ``text`` parameter.

    :param buffer_filters: string list of filters to be applied
     to the output of ``%def``\ s which are buffered, cached, or otherwise
     filtered, after all filters
     defined with the ``%def`` itself have been applied. Allows the
     creation of default expression filters that let the output
     of return-valued ``%def``\ s "opt out" of that filtering via
     passing special attributes or objects.

    :param bytestring_passthrough: When ``True``, and ``output_encoding`` is
     set to ``None``, and :meth:`.Template.render` is used to render,
     the `StringIO` or `cStringIO` buffer will be used instead of the
     default "fast" buffer.   This allows raw bytestrings in the
     output stream, such as in expressions, to pass straight
     through to the buffer.  This flag is forced
     to ``True`` if ``disable_unicode`` is also configured.

     .. versionadded:: 0.4
        Added to provide the same behavior as that of the previous series.

    :param cache_args: Dictionary of cache configuration arguments that
     will be passed to the :class:`.CacheImpl`.   See :ref:`caching_toplevel`.

    :param cache_dir:

     .. deprecated:: 0.6
        Use the ``'dir'`` argument in the ``cache_args`` dictionary.
        See :ref:`caching_toplevel`.

    :param cache_enabled: Boolean flag which enables caching of this
     template.  See :ref:`caching_toplevel`.

    :param cache_impl: String name of a :class:`.CacheImpl` caching
     implementation to use.   Defaults to ``'beaker'``.

    :param cache_type:

     .. deprecated:: 0.6
        Use the ``'type'`` argument in the ``cache_args`` dictionary.
        See :ref:`caching_toplevel`.

    :param cache_url:

     .. deprecated:: 0.6
        Use the ``'url'`` argument in the ``cache_args`` dictionary.
        See :ref:`caching_toplevel`.

    :param default_filters: List of string filter names that will
     be applied to all expressions.  See :ref:`filtering_default_filters`.

    :param disable_unicode: Disables all awareness of Python Unicode
     objects.  See :ref:`unicode_disabled`.

    :param enable_loop: When ``True``, enable the ``loop`` context variable.
     This can be set to ``False`` to support templates that may
     be making usage of the name "``loop``".   Individual templates can
     re-enable the "loop" context by placing the directive
     ``enable_loop="True"`` inside the ``<%page>`` tag -- see
     :ref:`migrating_loop`.

    :param encoding_errors: Error parameter passed to ``encode()`` when
     string encoding is performed. See :ref:`usage_unicode`.

    :param error_handler: Python callable which is called whenever
     compile or runtime exceptions occur. The callable is passed
     the current context as well as the exception. If the
     callable returns ``True``, the exception is considered to
     be handled, else it is re-raised after the function
     completes. Is used to provide custom error-rendering
     functions.

    :param format_exceptions: if ``True``, exceptions which occur during
     the render phase of this template will be caught and
     formatted into an HTML error page, which then becomes the
     rendered result of the :meth:`.render` call. Otherwise,
     runtime exceptions are propagated outwards.

    :param imports: String list of Python statements, typically individual
     "import" lines, which will be placed into the module level
     preamble of all generated Python modules. See the example
     in :ref:`filtering_default_filters`.

    :param future_imports: String list of names to import from `__future__`.
     These will be concatenated into a comma-separated string and inserted
     into the beginning of the template, e.g. ``futures_imports=['FOO',
     'BAR']`` results in ``from __future__ import FOO, BAR``.  If you're
     interested in using features like the new division operator, you must
     use future_imports to convey that to the renderer, as otherwise the
     import will not appear as the first executed statement in the generated
     code and will therefore not have the desired effect.

    :param input_encoding: Encoding of the template's source code.  Can
     be used in lieu of the coding comment. See
     :ref:`usage_unicode` as well as :ref:`unicode_toplevel` for
     details on source encoding.

    :param lookup: a :class:`.TemplateLookup` instance that will be used
     for all file lookups via the ``<%namespace>``,
     ``<%include>``, and ``<%inherit>`` tags. See
     :ref:`usage_templatelookup`.

    :param module_directory: Filesystem location where generated
     Python module files will be placed.

    :param module_filename: Overrides the filename of the generated
     Python module file. For advanced usage only.

    :param module_writer: A callable which overrides how the Python
     module is written entirely.  The callable is passed the
     encoded source content of the module and the destination
     path to be written to.   The default behavior of module writing
     uses a tempfile in conjunction with a file move in order
     to make the operation atomic.   So a user-defined module
     writing function that mimics the default behavior would be:

     .. sourcecode:: python

         import tempfile
         import os
         import shutil

         def module_writer(source, outputpath):
             (dest, name) = \\
                 tempfile.mkstemp(
                     dir=os.path.dirname(outputpath)
                 )

             os.write(dest, source)
             os.close(dest)
             shutil.move(name, outputpath)

         from mako.template import Template
         mytemplate = Template(
                         filename="index.html",
                         module_directory="/path/to/modules",
                         module_writer=module_writer
                     )

     The function is provided for unusual configurations where
     certain platform-specific permissions or other special
     steps are needed.

    :param output_encoding: The encoding to use when :meth:`.render`
     is called.
     See :ref:`usage_unicode` as well as :ref:`unicode_toplevel`.

    :param preprocessor: Python callable which will be passed
     the full template source before it is parsed. The return
     result of the callable will be used as the template source
     code.

    :param lexer_cls: A :class:`.Lexer` class used to parse
     the template.   The :class:`.Lexer` class is used by
     default.

     .. versionadded:: 0.7.4

    :param strict_undefined: Replaces the automatic usage of
     ``UNDEFINED`` for any undeclared variables not located in
     the :class:`.Context` with an immediate raise of
     ``NameError``. The advantage is immediate reporting of
     missing variables which include the name.

     .. versionadded:: 0.3.6

    :param uri: string URI or other identifier for this template.
     If not provided, the ``uri`` is generated from the filesystem
     path, or from the in-memory identity of a non-file-based
     template. The primary usage of the ``uri`` is to provide a key
     within :class:`.TemplateLookup`, as well as to generate the
     file path of the generated Python module file, if
     ``module_directory`` is specified.

    """

    lexer_cls = Lexer

    def __init__(self,
                 text=None,
                 filename=None,
                 uri=None,
                 format_exceptions=False,
                 error_handler=None,
                 lookup=None,
                 output_encoding=None,
                 encoding_errors='strict',
                 module_directory=None,
                 cache_args=None,
                 cache_impl='beaker',
                 cache_enabled=True,
                 cache_type=None,
                 cache_dir=None,
                 cache_url=None,
                 module_filename=None,
                 input_encoding=None,
                 disable_unicode=False,
                 module_writer=None,
                 bytestring_passthrough=False,
                 default_filters=None,
                 buffer_filters=(),
                 strict_undefined=False,
                 imports=None,
                 future_imports=None,
                 enable_loop=True,
                 preprocessor=None,
                 lexer_cls=None):
        if uri:
            self.module_id = re.sub(r'\W', "_", uri)
            self.uri = uri
        elif filename:
            self.module_id = re.sub(r'\W', "_", filename)
            drive, path = os.path.splitdrive(filename)
            path = os.path.normpath(path).replace(os.path.sep, "/")
            self.uri = path
        else:
            self.module_id = "memory:" + hex(id(self))
            self.uri = self.module_id

        u_norm = self.uri
        if u_norm.startswith("/"):
            u_norm = u_norm[1:]
        u_norm = os.path.normpath(u_norm)
        if u_norm.startswith(".."):
            raise exceptions.TemplateLookupException(
                "Template uri \"%s\" is invalid - "
                "it cannot be relative outside "
                "of the root path." % self.uri)

        self.input_encoding = input_encoding
        self.output_encoding = output_encoding
        self.encoding_errors = encoding_errors
        self.disable_unicode = disable_unicode
        self.bytestring_passthrough = bytestring_passthrough or disable_unicode
        self.enable_loop = enable_loop
        self.strict_undefined = strict_undefined
        self.module_writer = module_writer

        if compat.py3k and disable_unicode:
            raise exceptions.UnsupportedError(
                "Mako for Python 3 does not "
                "support disabling Unicode")
        elif output_encoding and disable_unicode:
            raise exceptions.UnsupportedError(
                "output_encoding must be set to "
                "None when disable_unicode is used.")
        if default_filters is None:
            if compat.py3k or self.disable_unicode:
                self.default_filters = ['str']
            else:
                self.default_filters = ['unicode']
        else:
            self.default_filters = default_filters
        self.buffer_filters = buffer_filters

        self.imports = imports
        self.future_imports = future_imports
        self.preprocessor = preprocessor

        if lexer_cls is not None:
            self.lexer_cls = lexer_cls

        # if plain text, compile code in memory only
        if text is not None:
            (code, module) = _compile_text(self, text, filename)
            self._code = code
            self._source = text
            ModuleInfo(module, None, self, filename, code, text)
        elif filename is not None:
            # if template filename and a module directory, load
            # a filesystem-based module file, generating if needed
            if module_filename is not None:
                path = module_filename
            elif module_directory is not None:
                path = os.path.abspath(
                    os.path.join(
                        os.path.normpath(module_directory),
                        u_norm + ".py"
                    )
                )
            else:
                path = None
            module = self._compile_from_file(path, filename)
        else:
            raise exceptions.RuntimeException(
                "Template requires text or filename")

        self.module = module
        self.filename = filename
        self.callable_ = self.module.render_body
        self.format_exceptions = format_exceptions
        self.error_handler = error_handler
        self.lookup = lookup

        self.module_directory = module_directory

        self._setup_cache_args(
            cache_impl, cache_enabled, cache_args,
            cache_type, cache_dir, cache_url
        )

    @util.memoized_property
    def reserved_names(self):
        if self.enable_loop:
            return codegen.RESERVED_NAMES
        else:
            return codegen.RESERVED_NAMES.difference(['loop'])

    def _setup_cache_args(self,
                          cache_impl, cache_enabled, cache_args,
                          cache_type, cache_dir, cache_url):
        self.cache_impl = cache_impl
        self.cache_enabled = cache_enabled
        if cache_args:
            self.cache_args = cache_args
        else:
            self.cache_args = {}

        # transfer deprecated cache_* args
        if cache_type:
            self.cache_args['type'] = cache_type
        if cache_dir:
            self.cache_args['dir'] = cache_dir
        if cache_url:
            self.cache_args['url'] = cache_url

    def _compile_from_file(self, path, filename):
        if path is not None:
            util.verify_directory(os.path.dirname(path))
            filemtime = os.stat(filename)[stat.ST_MTIME]
            if not os.path.exists(path) or \
                    os.stat(path)[stat.ST_MTIME] < filemtime:
                data = util.read_file(filename)
                _compile_module_file(
                    self,
                    data,
                    filename,
                    path,
                    self.module_writer)
            module = compat.load_module(self.module_id, path)
            del sys.modules[self.module_id]
            if module._magic_number != codegen.MAGIC_NUMBER:
                data = util.read_file(filename)
                _compile_module_file(
                    self,
                    data,
                    filename,
                    path,
                    self.module_writer)
                module = compat.load_module(self.module_id, path)
                del sys.modules[self.module_id]
            ModuleInfo(module, path, self, filename, None, None)
        else:
            # template filename and no module directory, compile code
            # in memory
            data = util.read_file(filename)
            code, module = _compile_text(
                self,
                data,
                filename)
            self._source = None
            self._code = code
            ModuleInfo(module, None, self, filename, code, None)
        return module

    @property
    def source(self):
        """Return the template source code for this :class:`.Template`."""

        return _get_module_info_from_callable(self.callable_).source

    @property
    def code(self):
        """Return the module source code for this :class:`.Template`."""

        return _get_module_info_from_callable(self.callable_).code

    @util.memoized_property
    def cache(self):
        return cache.Cache(self)

    @property
    def cache_dir(self):
        return self.cache_args['dir']

    @property
    def cache_url(self):
        return self.cache_args['url']

    @property
    def cache_type(self):
        return self.cache_args['type']

    def render(self, *args, **data):
        """Render the output of this template as a string.

        If the template specifies an output encoding, the string
        will be encoded accordingly, else the output is raw (raw
        output uses `cStringIO` and can't handle multibyte
        characters). A :class:`.Context` object is created corresponding
        to the given data. Arguments that are explicitly declared
        by this template's internal rendering method are also
        pulled from the given ``*args``, ``**data`` members.

        """
        return runtime._render(self, self.callable_, args, data)

    def render_unicode(self, *args, **data):
        """Render the output of this template as a unicode object."""

        return runtime._render(self,
                               self.callable_,
                               args,
                               data,
                               as_unicode=True)

    def render_context(self, context, *args, **kwargs):
        """Render this :class:`.Template` with the given context.

        The data is written to the context's buffer.

        """
        if getattr(context, '_with_template', None) is None:
            context._set_with_template(self)
        runtime._render_context(self,
                                self.callable_,
                                context,
                                *args,
                                **kwargs)

    def has_def(self, name):
        return hasattr(self.module, "render_%s" % name)

    def get_def(self, name):
        """Return a def of this template as a :class:`.DefTemplate`."""

        return DefTemplate(self, getattr(self.module, "render_%s" % name))

    def list_defs(self):
        """return a list of defs in the template.

        .. versionadded:: 1.0.4

        """
        return [i[7:] for i in dir(self.module) if i[:7] == 'render_']

    def _get_def_callable(self, name):
        return getattr(self.module, "render_%s" % name)

    @property
    def last_modified(self):
        return self.module._modified_time


class ModuleTemplate(Template):

    """A Template which is constructed given an existing Python module.

        e.g.::

        t = Template("this is a template")
        f = file("mymodule.py", "w")
        f.write(t.code)
        f.close()

        import mymodule

        t = ModuleTemplate(mymodule)
        print t.render()

    """

    def __init__(self, module,
                 module_filename=None,
                 template=None,
                 template_filename=None,
                 module_source=None,
                 template_source=None,
                 output_encoding=None,
                 encoding_errors='strict',
                 disable_unicode=False,
                 bytestring_passthrough=False,
                 format_exceptions=False,
                 error_handler=None,
                 lookup=None,
                 cache_args=None,
                 cache_impl='beaker',
                 cache_enabled=True,
                 cache_type=None,
                 cache_dir=None,
                 cache_url=None,
                 ):
        self.module_id = re.sub(r'\W', "_", module._template_uri)
        self.uri = module._template_uri
        self.input_encoding = module._source_encoding
        self.output_encoding = output_encoding
        self.encoding_errors = encoding_errors
        self.disable_unicode = disable_unicode
        self.bytestring_passthrough = bytestring_passthrough or disable_unicode
        self.enable_loop = module._enable_loop

        if compat.py3k and disable_unicode:
            raise exceptions.UnsupportedError(
                "Mako for Python 3 does not "
                "support disabling Unicode")
        elif output_encoding and disable_unicode:
            raise exceptions.UnsupportedError(
                "output_encoding must be set to "
                "None when disable_unicode is used.")

        self.module = module
        self.filename = template_filename
        ModuleInfo(module,
                   module_filename,
                   self,
                   template_filename,
                   module_source,
                   template_source)

        self.callable_ = self.module.render_body
        self.format_exceptions = format_exceptions
        self.error_handler = error_handler
        self.lookup = lookup
        self._setup_cache_args(
            cache_impl, cache_enabled, cache_args,
            cache_type, cache_dir, cache_url
        )


class DefTemplate(Template):

    """A :class:`.Template` which represents a callable def in a parent
    template."""

    def __init__(self, parent, callable_):
        self.parent = parent
        self.callable_ = callable_
        self.output_encoding = parent.output_encoding
        self.module = parent.module
        self.encoding_errors = parent.encoding_errors
        self.format_exceptions = parent.format_exceptions
        self.error_handler = parent.error_handler
        self.enable_loop = parent.enable_loop
        self.lookup = parent.lookup
        self.bytestring_passthrough = parent.bytestring_passthrough

    def get_def(self, name):
        return self.parent.get_def(name)


class ModuleInfo(object):

    """Stores information about a module currently loaded into
    memory, provides reverse lookups of template source, module
    source code based on a module's identifier.

     """
    _modules = weakref.WeakValueDictionary()

    def __init__(self,
                 module,
                 module_filename,
                 template,
                 template_filename,
                 module_source,
                 template_source):
        self.module = module
        self.module_filename = module_filename
        self.template_filename = template_filename
        self.module_source = module_source
        self.template_source = template_source
        self._modules[module.__name__] = template._mmarker = self
        if module_filename:
            self._modules[module_filename] = self

    @classmethod
    def get_module_source_metadata(cls, module_source, full_line_map=False):
        source_map = re.search(
            r"__M_BEGIN_METADATA(.+?)__M_END_METADATA",
            module_source, re.S).group(1)
        source_map = compat.json.loads(source_map)
        source_map['line_map'] = dict(
            (int(k), int(v))
            for k, v in source_map['line_map'].items())
        if full_line_map:
            f_line_map = source_map['full_line_map'] = []
            line_map = source_map['line_map']

            curr_templ_line = 1
            for mod_line in range(1, max(line_map)):
                if mod_line in line_map:
                    curr_templ_line = line_map[mod_line]
                f_line_map.append(curr_templ_line)
        return source_map

    @property
    def code(self):
        if self.module_source is not None:
            return self.module_source
        else:
            return util.read_python_file(self.module_filename)

    @property
    def source(self):
        if self.template_source is not None:
            if self.module._source_encoding and \
                    not isinstance(self.template_source, compat.text_type):
                return self.template_source.decode(
                    self.module._source_encoding)
            else:
                return self.template_source
        else:
            data = util.read_file(self.template_filename)
            if self.module._source_encoding:
                return data.decode(self.module._source_encoding)
            else:
                return data


def _compile(template, text, filename, generate_magic_comment):
    lexer = template.lexer_cls(text,
                               filename,
                               disable_unicode=template.disable_unicode,
                               input_encoding=template.input_encoding,
                               preprocessor=template.preprocessor)
    node = lexer.parse()
    source = codegen.compile(node,
                             template.uri,
                             filename,
                             default_filters=template.default_filters,
                             buffer_filters=template.buffer_filters,
                             imports=template.imports,
                             future_imports=template.future_imports,
                             source_encoding=lexer.encoding,
                             generate_magic_comment=generate_magic_comment,
                             disable_unicode=template.disable_unicode,
                             strict_undefined=template.strict_undefined,
                             enable_loop=template.enable_loop,
                             reserved_names=template.reserved_names)
    return source, lexer


def _compile_text(template, text, filename):
    identifier = template.module_id
    source, lexer = _compile(template, text, filename,
                             generate_magic_comment=template.disable_unicode)

    cid = identifier
    if not compat.py3k and isinstance(cid, compat.text_type):
        cid = cid.encode()
    module = types.ModuleType(cid)
    code = compile(source, cid, 'exec')

    # this exec() works for 2.4->3.3.
    exec(code, module.__dict__, module.__dict__)
    return (source, module)


def _compile_module_file(template, text, filename, outputpath, module_writer):
    source, lexer = _compile(template, text, filename,
                             generate_magic_comment=True)

    if isinstance(source, compat.text_type):
        source = source.encode(lexer.encoding or 'ascii')

    if module_writer:
        module_writer(source, outputpath)
    else:
        # make tempfiles in the same location as the ultimate
        # location.   this ensures they're on the same filesystem,
        # avoiding synchronization issues.
        (dest, name) = tempfile.mkstemp(dir=os.path.dirname(outputpath))

        os.write(dest, source)
        os.close(dest)
        shutil.move(name, outputpath)


def _get_module_info_from_callable(callable_):
    if compat.py3k:
        return _get_module_info(callable_.__globals__['__name__'])
    else:
        return _get_module_info(callable_.func_globals['__name__'])


def _get_module_info(filename):
    return ModuleInfo._modules[filename]
