# 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 _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]
